动态方法和MethodAccessException

本文关键字:MethodAccessException 方法 动态 | 更新日期: 2023-09-27 18:18:41

给出以下类:

class SomeBuilder<T>
{
    public static object Build(int index)
    {
        ...
    }
}
class SomeHelper
{
    public object GetBuildObj(object value)
    {
        var valuetype = value.GetType();
        var methodinfo = typeof(SomeBuilder<>).MakeGenericType(valuetype).GetMethod("Build");
        var handler = SomeDynamicHelper.GetMethodInvoker(methodinfo);
        var result = hander(null, new object[]{1});
    }
}

SomeBuilder是一个泛型类型,所以我需要调用MakeGenericType()来使事情正确。

当我传递一个普通类型,如'class person'作为值时,一切正常,这很好。

,但当我传递一个匿名类型,如:new {id=1},处理程序被成功创建。但是调用这个动态处理程序,我得到了一个MethodAccessException与这些消息:

"method "SomeDynamicHelper.(System.Object, System.Objec[])" try access method "SomeBuilder'1<<>f__AnonymousType0'1<System.Int32>>.Build(int)" failed.

任何帮助将不胜感激,谢谢。

如果您对SomeDynamicHelper感兴趣,请参阅:

http://www.codeproject.com/Articles/14593/A-General-Fast-Method-Invoker

edit1:

我在main中这样做了调用:

static void Main(string[] args)
{
    // pass a normal class, this will be fine
    var value = new Person { id = 1};
    new SomeHelper().GetBuildObj(value);  
    // pass a anonymous type
    var value = new { id = 1};
    new SomeHelper().GetBuildObj(value);  // oops, got a exception here!
}

edit2:

基于注释,我改变了我的代码:

class SomeHelper
{
    public object GetBuildObj(object value)
    {
        //this time i do not use the value, but create a new inner value:
        var valuenew = new { id = 1 };
        var valuetype = valuenew.GetType();
        var methodinfo = typeof(SomeBuilder<>).MakeGenericType(valuetype).GetMethod("Build");
        var handler = SomeDynamicHelper.GetMethodInvoker(methodinfo);
        var result = hander(null, new object[]{1});
    }
}

嗯,这次也不例外,但是……不幸的是,出现了一个新问题……也许我应该为新的问题开一个新的帖子。

谢谢大家的关注。

edit3:

嗨,经过一番挖掘,我也发现了一些有用的信息。例如,SomeDynamicHelper.GetMethodInvoker()代码如下:
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module);

这是我们在这里用来动态创建方法的核心。对于我们的上下文,我们需要在与SomeHelper和SomeBuilder相同的程序集中声明匿名类型。但是,如果我们不能报关,我们该怎么办呢?

好的,你可以调用DynamicMethod()最后一个参数(skipVisibility),设置为true!

希望这将帮助其他人有同样的问题:)

动态方法和MethodAccessException

"方法" SomeDynamicHelper。(系统。对象,system . Object[])"尝试访问方法"SomeBuilder'1<<>f__AnonymousType0'1>.Build(int)"

从这里你可以看到,动态方法试图运行一个名为Build的内部私有方法,为此你得到了MethodAccessException。

(匿名类型保存在新生成的类中)

添加InternalVisibleTo并不总是有帮助,因为只有当你可以重写匿名类型汇编(手动或拦截),只有当类型和方法是内部的,而不是私有的,它才有帮助。

在动态方法中,你可以将方法绑定到类型'module,并跳过可见性检查,但这有助于访问指定模块的私有成员,所以如果你试图访问的类型是在不同的程序集中,而类型'method是私有的,你不能做任何事情。

几乎。有一个"秘密"属性,您注入到您的程序集,称为IgnoreAccessChecksTo,然后除了有界模块和跳过可见性也许它会起作用。

您可以尝试在定义匿名类型的同一项目中使用[assembly: InternalsVisibleTo("Anonymously Hosted DynamicMethods Assembly")]

我在尝试使用ikvm转换的Guice注入c#类时遇到了类似的错误。修复的方法是将受影响的类(在本例中可能是SomeBuilder)公开,然后一切正常工作。

相关文章:
  • 没有找到相关文章