![](/img/trans.png)
[英]Microsoft.CSharp.RuntimeBinder.RuntimeBinderException Error
[英]Dynamic throwing Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on private types
我需要编写一些代码来克隆任何类型的HashSet,但是该类型事先未知。 由于缺少非通用接口(与字典不同,没有ISet接口,只有ISet <>),我不得不使用反射。 我决定让动态处理对我来说有效,但是现在当我运行以下代码(与真实世界的代码相比已大大简化)时,我遇到了一个看似非常奇怪的问题:
class Program
{
static void Main(string[] args)
{
HashSet<ReferenceType> source = new HashSet<ReferenceType>();
ExtMethodsCloning.DeepClone(source);
}
private class ReferenceType { }
}
public static class ExtMethodsCloning
{
public static void SomeCloningMethodThatHappensToCallClear(dynamic baseObj)
{
baseObj.Clear();
}
}
如果将DeepClone移至程序类或将ReferenceType公开,则它可以工作。 它必须以某种方式查看ReferenceType才能起作用。 即使我们只对调用Clear方法感兴趣,该方法甚至不是在ReferenceType上而是在HashSet <>上定义的。
如何解决此问题,而不必求助于手动进行反射工作? 记住类型在编译时是未知的,所以没有泛型。
编辑:我知道一个事实,在某个时候我将不得不创建新的实例,因此必须调用私有构造函数。 如果甚至可以使用动态调用构造函数,那么在这种情况下(并且通过使用反射来解决),我会期望出现错误,但是现在仅在HashSet上调用Clear时不会出现此错误。
我不明白这里需要动态。 我很确定您可以使用泛型来完成所需的工作。
编辑:如何通过反射调用通用方法:
static void Main(string[] args)
{
var hs1 = new HashSet<SomePrivateClass>();
CallClear(hs1);
}
public static void CallClear(object objectThatIsAHashSet)
{
var method = typeof(Program).GetMethod("Clear", BindingFlags.Public | BindingFlags.Static);
var hsGenericType = objectThatIsAHashSet.GetType().GetGenericArguments()[0];
var genericMethod = method.MakeGenericMethod(hsGenericType);
genericMethod.Invoke(null, new[] {objectThatIsAHashSet});
}
private class SomePrivateClass { }
public static void Clear<T>(HashSet<T> hs)
{
hs.Clear();
}
编辑2:为什么它不能与动态。
基本上,动态仅允许访问类型的公共成员。 因此,它不能用于调用私有成员或私有类型。 基本规则是,如果您无法使用代码的类型在代码段中引用该方法,则无法使用动态方法来访问该方法(即,不能使用动态方法来破坏封装)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.