C# 是否有一种方法可以在动态/expando中执行链式空检查?

C# 是否有一种方法可以在动态/expando中执行链式空检查?,c#,.net,dynamic,expandoobject,C#,.net,Dynamic,Expandoobject,C#具有有用的功能。我也解释得很好 我想知道当我的对象是dynamic/expando对象时,是否可以执行类似的检查。让我向您展示一些代码: 给定这个类层次结构 public class ClsLevel1 { public ClsLevel2 ClsLevel2 { get; set; } public ClsLevel1() { this.ClsLevel2 = new ClsLevel2(); // You can comment this line

C#具有有用的功能。我也解释得很好

我想知道当我的对象是dynamic/expando对象时,是否可以执行类似的检查。让我向您展示一些代码:

给定这个类层次结构

public class ClsLevel1
{
    public ClsLevel2 ClsLevel2 { get; set; }
    public ClsLevel1()
    {
        this.ClsLevel2 = new ClsLevel2(); // You can comment this line to test
    }        
}

public class ClsLevel2
{
    public ClsLevel3 ClsLevel3 { get; set; }
    public ClsLevel2()
    {
        this.ClsLevel3 = new ClsLevel3();
    }       
}

public class ClsLevel3
{
    // No child
    public ClsLevel3()
    {
    }
}
如果我执行这种链式空检查,它就会工作

ClsLevel1 levelRoot = new ClsLevel1();
if (levelRoot?.ClsLevel2?.ClsLevel3 != null)
{
     // will enter here if you DO NOT comment the content of the ClsLevel1 constructor
}
else
{
     // will enter here if you COMMENT the content of the ClsLevel1 
}
现在,我将尝试用动力学(ExpandoObjects)重现这种行为


有没有办法用动力学来模拟这种行为?我的意思是,在一长串成员中检查空值?

编辑:修复,因为ExpandoObjects和扩展方法不能很好地协同工作。稍微不太好看,但希望仍然可用

辅助方法:


如果希望以更自然的方式支持此功能,可以从DynamicObject继承并提供自定义实现:

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;
        }
    }
输出将是“Itworks!”。因为Boo不存在,所以我们得到一个null引用,以便null条件运算符可以工作


我们在这里做的是每次找不到属性时都返回对TryGetMember输出参数的null引用,并且我们总是返回true。

那么您想要的是
是否存在该属性的检查,而不是
null
检查?据我所知,没有办法做到这一点。如果没有办法,那么我们必须构建它。@mjwills在我的例子中,
这个属性是否存在
空检查
是相同的东西你测试过吗?我认为链接不起作用;尽管它会起作用。现在更新我的答案。扩展方法和动态不能很好地结合。另外,“Propertyname”字符串也很碍眼。谢谢@taquion,我做了一些测试,比如:1)使最后一个expando为null或不为null,2)使最后一个对象的属性为null或不为null,3)使“中间expando”为null或不为null,到目前为止,一切都很好,很高兴知道这一点\m/\m/有没有办法使MyExpando像默认的动态对象一样工作,我的意思是:dynamic d=newexpandoobject();d、 SomeProp=“foo”//works CustomDynamic c=新CustomDynamic();c、 SomeProp=“bar”//不行
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;
    }
}
if (DynamicExtensions.TryGetProperty(dinRoot, "DinLevel1.DinLevel2.DinLevel3") != null)
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;
        }
    }
 private static void Main(string[] args)
        {
            dynamic foo = new MyExpando();
            if (foo.Boo?.Lol ?? true)
            {
                Console.WriteLine("It works!");
            }
            Console.ReadLine();
        }