让DynamicObect的TryGetMember和TrySetMember在C#中返回一个类

时间:2018-04-12 19:15:37

标签: c# .net dynamicobject

我有一个继承自DynamicObject的班级 在这个课程中,我有一个TryGetMember我尝试评估一个静态类。

TryGetMember如何覆盖DynamicObject会导致静态类?

TL; DR

致电代码:

dynamic sut = new ReachIn();
sut.myclass.MyInnerStaticClass.MyProperty= "fortytwo";

我的DynamicObject类尝试将myclass作为MyClass实例返回。

internal class ReachIn : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = MyClass; // Does not compile.
        return true;
     }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        value = MyClass // Does not compile;
        return true;
    }
}

返回的是:

internal class MyClass
{
    internal static class MyInnerStaticClass
    {
        public static string MyProperty { get; set; }
    }
}

这个例子有点强迫。它只是动态对象的 very 简化示例,使得私有字段,属性,方法(和(尚未)类)可用于测试目的。我也知道不应该用这种方式写测试,但我有一个深奥的理由。或者因为我可以。

1 个答案:

答案 0 :(得分:2)

无论你的课堂设计如何,我都会表明你想要实现的是动态类型和反射。首先,动态对象只是一个对象,可以在TryGetMember等方法中使用某些字符串名称来执行某些操作。其次,使用字符串名称和反射,您可以对对象执行任何操作。如此简单的动态对象实现将与您的示例一起使用,如下所示:

internal class ReachIn : DynamicObject
{
    private readonly Type type;

    private readonly string @namespace;

    public ReachIn(Type type = null, string @namespace = null)
    {
        this.type = type;
        this.@namespace = @namespace;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (type == null)
        {
            result = new ReachIn(Type.GetType($"{@namespace}.{binder.Name}".Trim('.')));
            return true;
        }

        var member = type.GetMember(binder.Name).Single(); 

        if (member.MemberType == MemberTypes.NestedType)
        {
            result = new ReachIn((Type)member);
        }
        else if (member.MemberType == MemberTypes.Property)
        {
            result = ((PropertyInfo)member).GetValue(null);
        }
        else
        {
            result = null;
            return false;
        }

        return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        var member = type.GetMember(binder.Name).Single();

        if (member.MemberType == MemberTypes.Property)
        {
            ((PropertyInfo)member).SetValue(null, value);

            return true;
        }

        return false;
    }
}

因此它适用于具有公共修饰符的示例类:

public class MyClass
{
    public static class MyInnerStaticClass
    {
        public static string MyProperty { get; set; }
    }
}

使用此功能,您可以设置静态属性,如:

 dynamic sut = new ReachIn(@namespace: "ConsoleApp8");
 sut.MyClass.MyInnerStaticClass.MyProperty = "safd";

它仅针对您的示例进行了测试,因此对于其他情况,您需要提供一些额外的实现。更不用说它的表现因为反思而非常糟糕。