中等信任的匿名类型,与reflection而不是表达式一起使用

我在Medium Trust中对Linq查询进行自定义投影,我得到一个MethodAccessExceptionTypeAccessException抱怨reflection和安全权限。

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

 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

另一个类似的情况并没有解决问题

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

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

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

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

 [assembly: InternalsVisibleTo("mscorlib")] 

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

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

也许如果您的代码已签名,它就可以运行。 或许你甚至不需要调用Compile() – 也许这仅仅是为了测试? 添加对System.Core的引用值得一试。

如果你想对它进行unit testing而不是在浏览器中进行测试,我最近刚刚发布了一篇关于如何在Medium Trust中测试代码的post

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