我有一个框架,允许我使用键盘访问项目中对象的状态和方法。它在很大程度上依赖于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;
}
}我理解为什么会出现这样的问题,我可以看到一些可能的解决方案,比如寻找定义方法的类,并尝试将我的对象转换到该类,但这很麻烦。
是否有任何简单的解决方案,最好是严格根据即兴?
发布于 2012-12-31 17:34:48
因此,它在DLR中的工作方式是为调用提供一个上下文Type,这样它就可以确定哪些方法是可访问的。默认情况下,临时使用正在调用的对象的类型,因此它通常适用于大多数私有方法,但显然不适用于基类。
在您的例子中,您需要为即兴创建自己的上下文,这在文档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;
}
}https://stackoverflow.com/questions/14069840
复制相似问题