首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有一种方法可以在动态/扩展中执行链式空检查?

是否有一种方法可以在动态/扩展中执行链式空检查?
EN

Stack Overflow用户
提问于 2017-10-17 12:55:11
回答 2查看 1.6K关注 0票数 3

C#有有用的空条件算子。在这个答案中也有很好的解释。

我想知道,当我的对象是动态/扩展对象时,是否可以这样进行类似的检查。让我给你看一些代码:

给定这个类的层次结构

代码语言:javascript
运行
复制
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()
    {
    }
}

如果我执行这种链式空检查,它就能工作。

代码语言:javascript
运行
复制
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)来再现这种行为。

代码语言:javascript
运行
复制
dynamic dinRoot = new ExpandoObject();
dynamic DinLevel1 = new ExpandoObject();
dynamic DinLevel2 = new ExpandoObject();
dynamic DinLevel3 = new ExpandoObject();

dinRoot.DinLevel1 = DinLevel1;
dinRoot.DinLevel1.DinLevel2 = DinLevel2;
//dinRoot.DinLevel1.DinLevel2.DinLevel3 = DinLevel3; // You can comment this line to test

if (dinRoot?.DinLevel1?.DinLevel2?.DinLevel3 != null)
{
     // Obviously it will raise an exception because the DinLevel3 does not exists, it is commented right now.
}

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-17 13:45:11

如果您想以更自然的方式支持这一点,您可以从DynamicObject继承并提供一个自定义实现:

代码语言:javascript
运行
复制
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;
        }
    }

测试:

代码语言:javascript
运行
复制
 private static void Main(string[] args)
        {
            dynamic foo = new MyExpando();
            if (foo.Boo?.Lol ?? true)
            {
                Console.WriteLine("It works!");
            }
            Console.ReadLine();
        }

输出将是“它工作!”。由于Boo不存在,所以我们得到一个空引用,以便null条件运算符能够工作。

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

票数 5
EN

Stack Overflow用户

发布于 2017-10-17 13:10:27

编辑:修正,因为ExpandoObjects和扩展方法不能很好地结合在一起。稍微不太好,但希望仍然可以使用。

帮助者法:

代码语言:javascript
运行
复制
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;
    }
}

用法:

代码语言:javascript
运行
复制
if (DynamicExtensions.TryGetProperty(dinRoot, "DinLevel1.DinLevel2.DinLevel3") != null)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46790684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档