Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous type in medium trust, works with Reflection not with Expressions

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

like image 209
Yona Avatar asked Oct 10 '22 05:10

Yona


1 Answers

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.

like image 166
Stephen McDaniel Avatar answered Oct 14 '22 03:10

Stephen McDaniel