2012-12-28 22 views
4

我有一个框架允许我通过键盘访问项目中对象的状态和方法。它很大程度上依赖于ImpromptuInterface,这非常快速且灵活。使用ImpromptuInterface调用基类的私有成员

例如,我使用Impromptu.InvokeMember(myObject, methodName, castParameters)调用方法。它对公共和私人成员非常有用,但是当我尝试拨打myObject基类的私人成员时,我得到了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'MyType.MyMethod(Something)' is inaccessible due to its protection level

,揭示了问题的最简单的代码:

public class MainClass 
{ 
    public static void Main(string[] args) 
    { 
     var type = new PublicType(); 
     var other = new OtherType(); 
     Console.WriteLine(Impromptu.InvokeMember(other, "Method", 2)); //works 
     Console.WriteLine(Impromptu.InvokeMember(type, "Method", 2)); //crash 
    } 
} 

public class PublicType : OtherType 
{} 

public class OtherType 
{ 
    private bool Method(object a) 
    { 
     return a != null; 
    } 
} 

我明白为什么有这样的问题,我可以看到一些可能的解决方案,像在寻找类,其中定义的方法,并试图把我的对象投给那个班,但这很麻烦。

有没有简单的解决方案,最好严格依据Impromptu?

+0

使用ILSpy来查看'Impromptu.InvokeMember'是如何实现的 – sll

+0

好吧,它是开源的,但相当复杂。我不是真的进入DLR。 –

+0

你可以试试这个,而不是使用隐式类型变量,试试下面的OtherType type = new PublicType(); OtherType other = new OtherType();我试图看看Impromptu是否像反射绑定一样使用DeclaredOnly。 – humblelistener

回答

2

因此,它与DLR协同工作的方式是,您将调用作为上下文Type,以便确定可访问哪些方法。默认情况下,impromptu使用您正在调用的对象的类型,因此它通常适用于大多数私有方法,但显然不适用于基类。

对于您的情况,您需要为即兴创建自己的上下文,在文档UsagePrivate中提到,它适用于后期绑定类型以及接口。从文档中也不清楚,但情况是,您可以传入typeof()对象作为上下文。因此,在你的榜样,你可以这样做:

var context = InvokeContext.CreateContext; 

Console.WriteLine(Impromptu.InvokeMember(context(type, typeof(OtherType)), "Method", 2)); 

如果你要为通用的情况下做到这一点,它不漂亮,但你总是可以捕获该异常并递归尝试基本类型,它一般情况下工作第一次不应该放慢速度,而且班级层次通常不是很深,因为你只是互动地做了一次而不是几千次,所以应该没问题。

var context = InvokeContext.CreateContext; 
var type = target.GetType() 
while(true){ 
    try{ 
     Console.WriteLine(Impromptu.InvokeMember(context(target, type), "Method", 2)); 
     break; 
    }catch(RuntimeBinderException ex){ 
     type = type.BaseType; 
     if(type ==null) 
      throw ex; 
    } 
} 
+1

谢谢!很好的答案,它的作品。其实我已经验证过,但没有时间在这里写下来。作为一个侧面说明,Impromptu文档缺少关于这些上下文的一些文档,我已经发现如何通过查看图书馆的来源来做到这一点,这不是很方便......再次感谢。 –