9

信頼度が中程度の Web アプリで Expression をコンパイルしようとすると、MethodAccessException が発生します。中程度の信頼で式をコンパイルする別の方法、またはこの例外を回避するための回避策を知っている人はいますか?

例外をスローするコード:

Expression<Func<object>> efn = 
  Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));

Func<object> fn = efn.Compile(); // Exception thrown here

変数 plan は、次の実行計画を表す式です。

{
  Convert(Query(MyProjectNamespace.MyDatabaseTableObject).Provider).Execute
  (
    new QueryCommand(
    "SELECT [t0].[LinkId], [t0].[Url] FROM [dbo].[MyDatabaseTable] AS t0",
    value(System.String[]), 
    r0 => new MyDatabaseTableObject() 
    {
      Id = IIF(r0.IsDBNull(0), 0, 
        Convert(ChangeType(r0.GetValue(0), System.Int32))), 
      Url = IIF(r0.IsDBNull(1), null, 
        Convert(ChangeType(r0.GetValue(1), System.String)))
    }, 
    value(System.Collections.Generic.List[System.String])), 
    new [] {}
  )
}

完全なスタック トレース:

at System.Reflection.MethodBase.PerformSecurityCheck(Object obj, RuntimeMethodHandle method, IntPtr parent, UInt32 invocationFlags)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Linq.Expressions.ExpressionCompiler.AddGlobal(Type type, Object value)
at System.Linq.Expressions.ExpressionCompiler.GenerateConstant(ILGenerator gen, Type type, Object value, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConstant(ILGenerator gen, ConstantExpression c, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodInfo mi, ReadOnlyCollection`1 args, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodCallExpression mc, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConvert(ILGenerator gen, UnaryExpression u)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConditional(ILGenerator gen, ConditionalExpression b)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberAssignment(ILGenerator gen, MemberAssignment binding, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateBinding(ILGenerator gen, MemberBinding binding, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberInit(ILGenerator gen, ReadOnlyCollection`1 bindings, Boolean keepOnStack, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberInit(ILGenerator gen, MemberInitExpression init)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateLambda(LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.GenerateCreateDelegate(ILGenerator gen, LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateNew(ILGenerator gen, NewExpression nex, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodInfo mi, ReadOnlyCollection`1 args, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodCallExpression mc, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConvert(ILGenerator gen, UnaryExpression u)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateLambda(LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.CompileDynamicLambda(LambdaExpression lambda)
at System.Linq.Expressions.Expression`1.Compile()
at SubSonic.Linq.Structure.DbQueryProvider.Execute(Expression expression)
at SubSonic.Linq.Structure.QueryProvider.System.Linq.IQueryProvider.Execute(Expression expression)
at SubSonic.Linq.Structure.Query`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at WebApplication1._Default.Page_Load(Object sender, EventArgs e)
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
4

1 に答える 1

15

ここでの根本的な問題は、渡される型がSystem.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)public でないか、public でないコンストラクターを持っていることです。

今-あなたのコード例の単純さとスタックトレースの深さを考えると、問題は ではなく、plan内の式にあるplanと思います(マークの答えに対するコメントで、それは式でもあると言っているので)型を参照しますその後制限されます。

ここでエラーの原因となってConstantExpressionいる式は、制限された型でなければならない です。

ただし、これに関する唯一の紛らわしい点は、 にAddGlobal渡される型引数がActivator.CreateInstanceisStrongBox<T>であり、これは public であり、パブリック コンストラクターを持っていることです。これは、このエラーがあり得ないことを意味します。

StrongBox<T>しかし、おそらく、 Reflector を通して見ることができない何かが関連付けられています。

したがって、 で表される式ツリー全体planを調べ、 s で参照されるすべての型を調べて、ConstantExpressionそれらがすべてアクセス可能であることを確認します。それを行った後、すべてのタイプがアクセス可能であることが示されても、このエラーが引き続き発生する場合は、フレームワークのバグである可能性があります。

しかし、私は、そのようなバグはConstantExpression!

EDIT (以前の編集を置き換える) WITH THE ANSWER

私はそれを手に入れました、そしてそれは非常に微妙な問題です。中程度の信頼で実行するように構成された aspx ページで、次の小さなコードを使用して再現できます。

Type t = typeof([any type you fancy]);
Expression expr = Expression.Constant(t);
var lambda = Expression.Lambda<Func<Type>>(expr);
var del = lambda.Compile();
Response.Write(del().ToString());

したがって、あなたが提供したコードではChangeTypeType(コードが見えませんが、それは合理的な推測!)。

ConstantExpressionインスタンスとしての表現に焼き付けていTypeます。パラメータをどのように絞り込んだかは聞かないでください - 多くのスタッククロールとリフレクタが機能します;)

私の回答の前半で述べたように、式ツリー コンパイラが使用するコードが MethodAccessException を作成する方法を確認するのは困難です。これは、常にStrongBox<T>型のパブリック ctor にアクセスしているためです。

ただし、ジェネリックとして渡された型が public でない場合は混乱します。「しかし、待ってください」とあなたは言います、「Type公開されています!」.

そうかもしれませんが、Type実行時に返されるインスタンスはtypeof()orGetType()ではありません - それはのインスタンスですRuntimeType- which is internal .

これが、上記のコード スニペットでも同じエラーが発生する理由でもあります。

修正

fromのType引数を生成するコードを変更しますChangeType(,)

Expression.Constant([type])

(現時点ではほぼ保証します)

Expression.Constant([type], typeof(Type))

Typeの反映された型の代わりに、定数にパブリックを使用するようにコンパイラに明示的に指示しているため、これは機能しますRuntimeType

この修正を前のブロックのサンプル コードに適用して再実行することで、この修正をテストできます。

于 2010-07-07T13:34:55.210 に答える