Anonymous type in medium trust, works with Reflect

2019-04-08 19:06发布

问题:

I'm doing custom projections on Linq queries in Medium Trust and I get a MethodAccessException or TypeAccessException complaining about reflection and security rights.

I've simplified the code to the following:

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 }

In Full Trust, anon2 and anon3 will be created. In Medium Trust only anon2 will be created.

Another similar situation did not solve the issue

回答1:

This is caused because anonymous types are created as internal by the compiler. That means code outside of your assembly won't be able to access the types. When you do the reflection yourself, all the calls are coming from your assembly so it is allowed. But when you introduce expressions, the calls start coming from framework DLLs and so they get stopped.

An easy way to solve problems of this nature is with the InternalsVisibleTo attribute. By just adding this:

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

you'll be able to create the lambda. However, when you go to compile it, you get a similar permission exception. In that case, the Compile method ends up triggering some code in mscorlib.dll to try to access your type. I tried adding:

[assembly: InternalsVisibleTo("mscorlib")]

but that didn't seem to work. I think it might have to do with the fact that mscorlib is strongly signed. According to the documentation of InternalsVisislbeTo:

Both the current assembly and the friend assembly must be unsigned, or both must be signed with a strong name.

Perhaps if your code was signed, it would work. Or perhaps you don't even need the call to Compile() - maybe that was just for testing? Adding the reference to System.Core is worth a try.



回答2:

If you'd like to unit test this rather than keep testing in a browser, I've just put up a post just recently on how to unit test code in Medium Trust

Part three has a downloadable assembly with a base class you can use for any NUnit test fixture, and it contains links to the other parts: http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with-nunitpart-three-umbraco-framework-testing/