c# – 使用ImpromptuInterface调用基类的私有成员

我有一个框架,允许我使用键盘访问项目中的对象的状态和方法.它在很大程度上依赖于
ImpromptuInterface,这是一个伟大,快速和灵活的东西.

例如,我使用Impromptu.InvokeMember(myObject,methodName,castParameters)调用方法.它适用于公共和私有成员,但是当我尝试调用myObject基类的私有成员时,我得到Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:由于其保护级别,’MyType.MyMethod(Something)’无法访问.

显示问题的最简单的代码:

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?

最佳答案 因此,它与DLR一起工作的方式是为调用提供上下文类型,以便它可以确定可访问的方法.即便即时使用您正在调用的对象的类型,因此它通常适用于大多数私有方法,但显然不适用于基类.

在您的情况下,您需要为即兴创建自己的上下文,这在文档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;
   }
}
点赞