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

时间:2011-08-17 16:23:23

标签: c# linq reflection anonymous-types medium-trust

我正在使用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。在中型信任中,只会创建anon2

另一个similar situation没有解决问题

2 个答案:

答案 0 :(得分:4)

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

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

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

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

[assembly: InternalsVisibleTo("mscorlib")]

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

  

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

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

答案 1 :(得分:0)

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

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