既存のクラスライブラリをSilverlightに移植しています。ラムダ式のコンパイルを頻繁に使用しましたが、そのためにセキュリティの問題が発生しています。
特に、クライアントSLアプリの匿名クラスがラムダ式に参加している場合、それをコンパイルできません。MethodAccessException
次のスタックトレースでを取得します。
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)
クライアントSLアプリで匿名クラスをクラスライブラリに公開しようとしInternalsVisibleTo
ましたが、役に立ちませんでした。実際には役立つはずですが、なぜ役に立たないのか理解できません。
何か案は?
更新:
問題はラムダ式ではなく、動的なジェネリックメソッドの呼び出しにあることがわかりました:
クラスライブラリに次のコードがある場合:
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
}
}
そして、次のようにアプリからStaticReceiveメソッドを呼び出します。
class InternalClass { }
void MethodInUserApp()
{
var x = new InternalClass();
LibClass.StaticReceive(x);
}
正常に動作しますが、を使用するDynamicReceive
と失敗します。CLRは、メソッドx
内のパラメーターをジェネリックではなくタイプと見なしているようです。また、ライブラリからアクセスできないため、その呼び出しを禁止しています。Process
InternalClass
T
InternalClass
バグのようですね。