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

C# 使用ImpromptuInterface调用基类的私有成员,c#,impromptu-interface,C#,Impromptu Interface,我有一个框架,允许我使用键盘访问项目中对象的状态和方法。它很大程度上依赖于,这是伟大的,快速和灵活的东西 例如,我使用Impromptu.InvokeMember(myObject、methodName、castParameters)调用方法。它对公共和私有成员都很有效,但是当我尝试调用myObject基类的私有成员时,我得到了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“MyType.MyMethod(Something)”由于其

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

例如,我使用
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;
    }
}
我理解为什么会出现这样的问题,并且我可以看到一些可能的解决方案,比如寻找类,在其中定义方法,并尝试将我的对象强制转换到该类,但这相当麻烦


是否有任何简单的解决方案,最好是严格基于即兴的?

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

在您的情况下,您需要为impromptu创建自己的上下文,这在文档中提到过,它适用于后期绑定类型以及接口。文档中也不清楚,但事实上,您可以为上下文传入一个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;
   }
}

使用ILSpy查看
Impromptu.InvokeMember
是如何实现的。它是开源的,但相当复杂。我对DLR不是很感兴趣。你能试试这个吗?不要使用隐式类型的变量,试试下面的OtherType=new PublicType();OtherType other=新的OtherType();我想看看即兴是不是像反射绑定一样使用DeclaredOnly,这是不可能的。对象是由某人在某处创建的,我只接收一个
对象
,查找方法或字段,然后执行/赋值。谢谢!答案很好,而且很有效。事实上,我已经核实过了,但没有时间在这里写下来。顺便说一句,即兴文档缺少一些关于这些上下文的文档,我通过查看库中的源代码找到了如何做到这一点,这并不是很方便。。。再次感谢。