在私有类型上动态抛出 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException [英] Dynamic throwing Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on private types

查看:88
本文介绍了在私有类型上动态抛出 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写一些代码来克隆任何类型的 HashSet,但该类型事先未知.由于缺少非通用接口(与字典不同,没有 ISet 接口只是一个 ISet<>),我必须使用反射.我决定让动态处理反射为我工作,但现在我在运行以下代码时遇到了一个看似非常奇怪的问题(从现实世界的代码中大大简化了):

I need to write some code to clone a HashSet of any type but the type is not known beforehand. Due to the lack of a non generic interface (unlike dictionary there is no ISet interface just a ISet<>) I have to use reflection. I decided to let dynamic handle the reflection work for me but now iam running into a seemingly very weird problem when I run the following code (heavily simplified from the real world code):

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<>.

If you move DeepClone to the program class or make ReferenceType public it works. It somehow needs to see ReferenceType in order to work. Even though we are only interested in calling the Clear method which isnt even defined on ReferenceType but on HashSet<>.

如何在不必求助于手动进行反射工作的情况下解决此问题?请记住,编译时不知道类型,因此没有泛型.

How can I workaround this while not having to resort to manually doing the reflection work? Remember the type is not know at compile time so no generics.

我知道在某些时候我必须创建新实例,因此必须调用私有构造函数.如果甚至可以使用动态调用构造函数,我希望在这种情况下会出现错误(并通过使用反射来解决它),但现在仅在 HashSet 上调用 Clear 时不会.

iam aware of the fact that at some point I would have to create new instances and thus have to call private constructors. If its even possible to call a constructor using dynamic I would expect an error in that case (and workaround it by using reflection) but not now when just calling Clear on the HashSet.

推荐答案

我不明白这里需要动态.我很确定你可以用泛型做你需要的.

I don't understand the need for dynamic here. I'm pretty sure you can do what you need with generics.

如何通过反射调用泛型方法:

How to call a generic method by reflection:

 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:为什么它不适用于动态.

EDIT 2: Why doesn't it work with dynamic.

基本上,动态只允许访问类型的公共成员.因此,它不能用于调用私有成员或私有类型.基本规则是,如果你不能使用它的类型在一段代码中引用一个方法,你就不能使用动态访问它(即你不能使用动态来破坏封装).

Basically, dynamic only allows access to public members of a type. As such, it cannot be used to call either a private member, or a private type. The basic rule is that if you could not refer to a method in a piece of code using it's type, you cannot access it using dynamic (i.e. you can't use dynamic to break encapsulation).

这篇关于在私有类型上动态抛出 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆