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
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.
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/