【问题标题】:dynamic method and the MethodAccessException动态方法和 MethodAccessException
【发布时间】:2013-06-12 14:28:23
【问题描述】:

给定以下类:

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() 来解决问题。

当我为值传递一个像“类人”这样的普通类型时,一切正常,这很好。

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

"method "SomeDynamicHelper.(System.Object, System.Objec[])" 尝试访问方法"SomeBuilder'1&lt;&lt;&gt;f__AnonymousType0'1&lt;System.Int32&gt;&gt;.Build(int)" 失败。

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

顺便说一句,如果您对 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 相同的程序集中声明匿名类型。但是,如果我们不能做声明,我们该怎么办?

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

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

【问题讨论】:

  • “但是当我传递匿名类型时”并不是很清楚您的意思 - 如果您提供一个简短但完整的失败示例,这将非常有帮助。匿名类型没有名为Build...的方法
  • 抱歉不清楚。我做了一些编辑,希望这将有助于澄清我的问题。
  • 什么是SomeDynamicHelper
  • @CodingWithSpike 嗨,你可以看到这个:codeproject.com/Articles/14593/A-General-Fast-Method-Invoker
  • @pinopino:所有这些类都在哪个程序集中?请记住,匿名类型是内部的。

标签: c# generics dynamic reflection


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    “方法“SomeDynamicHelper.(System.Object, System.Objec[])”尝试访问方法“SomeBuilder'1f__AnonymousType0'1>.Build(int)”

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

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

    添加InternalVisibleTo 并不总是有帮助,因为它只有在您可以重写匿名类型程序集(手动或使用拦截)并且只有当类型和方法是内部而不是私有时才有帮助。

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

    差不多吧。您向程序集注入了一个“秘密”属性,称为IgnoreAccessChecksTo,然后除了有界模块和跳过可见性之外,它可能会起作用。

    【讨论】:

      【解决方案3】:

      我在尝试使用 IKVM 转换的 Guice 注入的 C# 类时遇到了类似的错误。修复只是将受影响的类(在这种情况下可能是SomeBuilder)公开,一切正常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-15
        • 1970-01-01
        • 1970-01-01
        • 2022-12-16
        • 2011-10-09
        • 2023-03-15
        • 2011-07-15
        相关资源
        最近更新 更多