让 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";
它仅使用您的示例进行了测试,因此对于其他情况,您需要提供一些额外的实现。更不用说反射了,性能会很差
我有一个 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";
它仅使用您的示例进行了测试,因此对于其他情况,您需要提供一些额外的实现。更不用说反射了,性能会很差