让 DynamicObject 的 TryGetMember 和 TrySetMember return a class in C#

Let DynamicObect's TryGetMember and TrySetMember return a class in C#

我有一个 class 继承自 DynamicObject
在这个 class 中,我有一个 TryGetMember ,我尝试将其评估为静态 class.

如何从 DynamicObject 覆盖 TryGetMember 导致静态 class?

TL;DR

调用代码:

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

我的 DynamicObject class 尝试 return 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;
    }
}

什么是 returned 在这里:

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

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

无论您的 class 设计如何,我都将展示您尝试实现的目标可以通过动态类型和反射实现。首先,动态对象只是一个对象,它可以在 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:

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

有了这个你可以设置你的静态属性像:

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

它仅使用您的示例进行了测试,因此对于其他情况,您需要提供一些额外的实现。更不用说反射了,性能会很差