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

Yon*_*ona 5 c# linq reflection medium-trust anonymous-types

我正在对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 }
Run Code Online (Sandbox Code Playgroud)

在完全信任,anon2并且anon3将被创建.仅在中型信任anon2中将创建.

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

Ste*_*iel 4

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

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

[assembly: InternalsVisibleTo("System.Core")]
Run Code Online (Sandbox Code Playgroud)

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

[assembly: InternalsVisibleTo("mscorlib")]
Run Code Online (Sandbox Code Playgroud)

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

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

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