繁体   English   中英

在私有类型上动态抛出Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM