Is there a way to perform a chained null check in a dynamic/expando?

后端 未结 2 1760
栀梦
栀梦 2021-01-14 19:09

C# has the usefull Null Conditional Operator. Well explained in this answer too.

I was wondering if it is possible to do a similar check like this when my object is

相关标签:
2条回答
  • 2021-01-14 19:42

    If you want to support this in a more natural way you can inherit from DynamicObject and provide a custom implementation:

    class MyExpando : DynamicObject
        {
            private readonly Dictionary<string, object> _dictionary = new Dictionary<string, object>();
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                var name = binder.Name.ToLower();
                result = _dictionary.ContainsKey(name) ? _dictionary[name] : null;
                return true;
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                _dictionary[binder.Name.ToLower()] = value;
                return true;
            }
        }
    

    Testing:

     private static void Main(string[] args)
            {
                dynamic foo = new MyExpando();
                if (foo.Boo?.Lol ?? true)
                {
                    Console.WriteLine("It works!");
                }
                Console.ReadLine();
            }
    

    The output will be "It works!". Since Boo does not exist we get a null reference so that the Null Conditional Operator can work.

    What we do here is to return a null reference to the output parameter of TryGetMember every time a property is not found and we always return true.

    0 讨论(0)
  • 2021-01-14 19:48

    EDIT: fixed, as ExpandoObjects and extension methods do not work well together. Slightly less nice, but hopefully still usable.

    Helper method(s):

    public static class DynamicExtensions
    {
        public static Object TryGetProperty(ExpandoObject obj, String name)
        {
            return name.Split('.')
                       .Aggregate((Object)obj, (o, s) => o != null
                                                          ? TryGetPropertyInternal(o, s)
                                                          : null);
        }
    
        private static Object TryGetPropertyInternal(Object obj, String name)
        {
            var dict = obj as IDictionary<String, Object>;
            return (dict?.ContainsKey(name) ?? false) ? dict[name] : null;
        }
    }
    

    Usage:

    if (DynamicExtensions.TryGetProperty(dinRoot, "DinLevel1.DinLevel2.DinLevel3") != null)
    
    0 讨论(0)
提交回复
热议问题