Domanda

Quando si tenta di compilare un'espressione in una web app attendibilità media mi sto un MethodAccessException. Qualcuno sa di un altro modo per compilare un'espressione sotto trust media o una soluzione per evitare questa eccezione?

Il codice che genera l'eccezione:

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

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

Il piano variabile è un'espressione che rappresenta il seguente piano di esecuzione:

{
  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 [] {}
  )
}

La traccia completa dello stack:

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)
È stato utile?

Soluzione

Il problema alla base è che il tipo sia passato al System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) non è o pubblico, o ha un costruttore che non è pubblico.

Ora - data la semplicità del tuo esempio di codice rispetto alla profondità della stacktrace credo le bugie problema non in plan, ma in un'espressione all'interno plan (dal momento che dici nel tuo commento alla risposta di Marc che è anche un'espressione) che i riferimenti del tipo che viene poi limitata.

L'espressione che è la fonte dell'errore ecco un ConstantExpression che deve essere del tipo ristretto.

L'unica cosa confusione su questo, tuttavia, è che il tipo di argomento che AddGlobal passa al Activator.CreateInstance è StrongBox<T>, che è pubblica e ha un costruttore pubblico -. Che implicherebbe che questo errore dovrebbe essere impossibile

Forse, però, c'è qualcosa di nascosto associato a StrongBox<T> che non possiamo vedere attraverso riflettore.

Quindi, vorrei essere a guardare l'intero albero di espressione rappresentata da plan ed esaminando tutti i tipi di riferimento in ConstantExpressions per assicurare che sono tutti accessibili. Se dopo aver fatto che tutti i tipi sono indicati per essere accessibili, questo errore si verifica ancora, allora potrebbe essere un bug nel quadro.

Tuttavia - avrei pensato che un tale errore sarebbe stato trovato già da qualcosa di semplice come un ConstantExpression

Modifica (Edit Sostituzione precedente) CON LA RISPOSTA

ho capito, ed è un problema molto sottile. È possibile riprodurre con questo po 'di codice in una pagina aspx che è configurato per l'esecuzione in media fiducia:

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());

Quindi, il codice che ci hai fornito, è l'espressione che rappresenta il secondo argomento di ChangeType (mi ha portato un po 'per rendersi conto che questo è un metodo di Sonic Sub), che sembra essere un Type (non può vedere il codice, ma credo che sia una supposizione ragionevole!).

E 'cotto nell'espressione come ConstantExpression di un'istanza Type. Non chiedo come ho ristretto il parametro - un sacco di pila che strisciano e di lavoro parabola;)

Come accennato nella prima metà della mia risposta, è difficile vedere come il codice che l'espressione Albero usi compilatore potrà mai creare un MethodAccessException, dal momento che è sempre l'accesso alla ctor pubblico del tipo StrongBox<T>.

Tuttavia, sarebbe si arrabbiano se il tipo passato come il generico non è pubblico. "Ma aspetta," dici, "Type è pubblico!".

Questo potrebbe essere, ma l'istanza Type restituita in fase di esecuzione da typeof() o GetType() non è - è un esempio di RuntimeType - che è interno

.

Il che è anche il motivo per il frammento di codice di cui sopra sarà anche innescare lo stesso errore.

La correzione

Modificare il codice che produce l'argomento Type per ChangeType(,) da

Expression.Constant([type])

(che io quasi garantire che sia al momento) a

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

Questo funziona, perché si sta dicendo esplicitamente al compilatore di utilizzare il Type pubblico per la costante, invece che il tipo di riflesso RuntimeType.

È possibile verificare questa correzione applicandolo al mio codice di esempio nel blocco precedente e ri-esecuzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top