中等信任的匿名类型,使用反射而不是表达式

Posted

技术标签:

【中文标题】中等信任的匿名类型,使用反射而不是表达式【英文标题】:Anonymous type in medium trust, works with Reflection not with Expressions 【发布时间】:2011-10-29 02:24:29 【问题描述】:

我正在对 Medium Trust 中的 Linq 查询进行自定义预测,我收到 MethodAccessExceptionTypeAccessException 抱怨反射和安全权利。

我已将代码简化为以下内容:

var anon1 = new  Name = "Bill Gates" ;
var ctor = anon1.GetType().GetConstructors().First();

// With native Reflection it works
var anon2 = ctor.Invoke(new object[]  "Steve Ballmer" );

var expr = Expression.New(ctor, Expression.Constant("Scott Guthrie"));
var lamb = Expression.Lambda(expr);      // This throws in Medium Trust

var anon3 = lamb.Compile().DynamicInvoke();

anon1.ToString();        // -->  Name = Bill Gates 
anon2.ToString();        // -->  Name = Steve Ballmer 
anon3.ToString();        // -->  Name = Scott Guthrie 

在完全信任的情况下,将创建 anon2anon3。在 Medium Trust 中,只会创建 anon2

另一个similar situation 没有解决问题

【问题讨论】:

所以我一直在尝试重现这一点。你在 .NET4 上吗?你对如何复制有什么建议吗?我假设 anon1 在所有情况下都成功创建?您是否尝试过不使用 DynamicInvoke 而直接调用委托? 我使用的是 .NET 4。要重现它,您必须在中等信任下运行此代码。 代码在Expression.Lambda() 调用上抛出,而不是在Compile() 上抛出 【参考方案1】:

这是因为匿名类型被编译器创建为internal。这意味着程序集之外的代码将无法访问这些类型。当您自己进行反射时,所有调用都来自您的程序集,因此是允许的。但是当您引入表达式时,调用开始来自框架 DLL,因此它们会停止。

解决此类问题的一个简单方法是使用InternalsVisibleTo 属性。只需添加以下内容:

[assembly: InternalsVisibleTo("System.Core")]

您将能够创建 lambda。但是,当你去编译它时,你会得到一个类似的权限异常。在这种情况下,Compile 方法最终会触发 mscorlib.dll 中的一些代码来尝试访问您的类型。我尝试添加:

[assembly: InternalsVisibleTo("mscorlib")]

但这似乎不起作用。我认为这可能与 mscorlib 是强签名的事实有关。根据 InternalsVisislbeTo 的文档:

当前程序集和友元程序集都必须是无符号的,或者 两者都必须使用强名称签名。

也许如果您的代码已签名,它会起作用。或者你甚至不需要调用 Compile() - 也许这只是为了测试?添加对 System.Core 的引用值得一试。

【讨论】:

原生反射如何起作用?由于反射类是在其他程序集中定义的,所以我希望有相同的行为。 代码在 Expression.Lambda() 调用上抛出,而不是在 Compile() 上抛出 反射类是进行权限检查的类。所以他们从调用者的上下文中进行检查。通过直接反射,您就是调用者。对于表达式,Linq.Expression 类是调用者。 即使使用 InternalsVisislbeTo,它仍然会抛出 Expression.Lambda?我能够以中等信任执行 Lambda 调用。你能发布异常详细信息吗?另外,这是一个什么样的应用程序? WinForm、命令行、ASP.Net 等? 该代码是 Microsoft Dynamics CRM 插件的一部分。所有插件都在中等信任下运行并且必须签名。我尝试使用公钥添加 InternalsVisibleTo,但没有成功。【参考方案2】:

如果您想对此进行单元测试而不是继续在浏览器中进行测试,我最近刚刚发布了一篇关于如何在 Medium Trust 中对代码进行单元测试的帖子

第三部分有一个可下载的程序集,其中包含可用于任何 NUnit 测试夹具的基类,它包含指向其他部分的链接:http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with-nunitpart-three-umbraco-framework-testing/

【讨论】:

以上是关于中等信任的匿名类型,使用反射而不是表达式的主要内容,如果未能解决你的问题,请参考以下文章

使用 lambda 而不是显式匿名内部类时的不同泛型行为

Kotlin函数 ⑤ ( 匿名函数变量类型推断 | 匿名函数参数类型自动推断 | 匿名函数又称为 Lambda 表达式 )

如何使用表达式构建匿名类型?

确定类型是不是为匿名类型

如何使用匿名方法返回值?

通过 WCF 传递匿名类型的实例