views:

184

answers:

1

I'm porting an existing class library to Silverlight. I used lambda expression compilation a lot and now I'm experiencing security problems because of it.

In particular, if an anonymous class from a client SL app is participating in a lambda expression, I cannot compile it: I get a MethodAccessException with the following stack trace:

MethodBase.PerformSecurityCheck(Object obj, RuntimeMethodHandle method, IntPtr parent, UInt32 invocationFlags)
RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
MethodBase.Invoke(Object obj, Object[] parameters)
Expression.Lambda(Type delegateType, Expression body, IEnumerable<T> parameters)
Expression.Lambda(Type delegateType, Expression body, ParameterExpression[] parameters)
Expression.Lambda(Expression body, ParameterExpression[] parameters)

I tried to use InternalsVisibleTo in the client SL app to expose anonymous classes to my class library, but it didn't help. Actually it should help, but I cannot understand why it does not.

Any ideas?

UPDATE:
I've figured out that the problem is not in lambda expressions, but in dynamic generic method invocation:

If we have the following code in a class library:

public class LibClass
{
    public static void StaticReceive<T>(T x)
    {
        Process<T>(x);
    }
    public static void DynamicReceive(object x)
    {
        typeof(LibClass).GetMethod("Process", BindingFlags.NonPublic | BindingFlags.Static)
            .MakeGenericMethod(x.GetType())
            .Invoke(null, new object[] { x });
    }
    static void Process<T>(T x)
    {
        // some work with typed x
    }
}

and we call the StaticReceive method from the app like this:

class InternalClass { }
void MethodInUserApp()
{
    var x = new InternalClass();
    LibClass.StaticReceive(x);
}

it works OK, but if we use DynamicReceive, it fails. It looks like CLR considers the x parameter in the Process method as of type InternalClass, not generic T, and since InternalClass is not accessible for the library, forbids its invocation.

It looks like a bug, no?

+1  A: 

Solved: Add the following code to your AssemblyInfo.cs:

[assembly: InternalsVisibleTo("System.Core, PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649" +
"383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb7" +
"7e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638" +
"fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c" +
"123b37ab")]

Discussed in the Silverlight forum

Nodir