中等信任的匿名类型,使用反射而不是表达式
Posted
技术标签:
【中文标题】中等信任的匿名类型,使用反射而不是表达式【英文标题】:Anonymous type in medium trust, works with Reflection not with Expressions 【发布时间】:2011-10-29 02:24:29 【问题描述】:我正在对 Medium Trust 中的 Linq 查询进行自定义预测,我收到 MethodAccessException
或 TypeAccessException
抱怨反射和安全权利。
我已将代码简化为以下内容:
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
在完全信任的情况下,将创建 anon2
和 anon3
。在 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/
【讨论】:
以上是关于中等信任的匿名类型,使用反射而不是表达式的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin函数 ⑤ ( 匿名函数变量类型推断 | 匿名函数参数类型自动推断 | 匿名函数又称为 Lambda 表达式 )