Pregunta

Al intentar compilar una expresión en una aplicación web confianza medio me estoy poniendo un MethodAccessException. ¿Alguien sabe de otra manera para compilar una expresión de confianza medio bajo o una solución para evitar esta excepción?

El código que produce la excepción:

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

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

El plan variable es una expresión que representa el siguiente plan de ejecución:

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

El seguimiento de pila completo:

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)
¿Fue útil?

Solución

El problema que subyace aquí es que el tipo que se pasa al System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) no es de carácter público, o tiene un constructor que no es pública.

Ahora - dada la simplicidad de su ejemplo de código en comparación con la profundidad de la StackTrace Creo que las mentiras problema No existen plan, pero en una expresión dentro de plan (ya que usted dice en su comentario sobre la respuesta de Marc que también es una expresión) que hace referencia al tipo que se limita entonces.

La expresión que es la fuente del error aquí es un ConstantExpression que debe ser del tipo restringido.

La única cosa sobre este confuso, sin embargo, es que el argumento de tipo AddGlobal que pasa a Activator.CreateInstance es StrongBox<T>, que es público y tiene un constructor público -. Lo que implicaría que este error debería ser imposible

Tal vez, sin embargo, hay algo escondido asociado con StrongBox<T> que no podemos ver a través del reflector.

Por lo tanto, estaría buscando en todo el árbol de expresión representada por plan y el examen de todos los tipos de referencia en ConstantExpressions para asegurarse de que son todos accesibles. Si después de hacer que todos los tipos se muestran para ser accesible, este error se sigue produciendo, entonces podría ser un error en el marco.

Sin embargo - Me habría pensado que un error tal hubiera sido encontrados ya para algo tan simple como un ConstantExpression

Edit (Sustitución edición anterior) CON LA RESPUESTA

Lo tengo, y es un problema muy sutil. Puede reproducir con este pequeño fragmento de código en una página aspx que está configurado para funcionar en un medio de confianza:

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

Por lo tanto, en el código que nos ha facilitado, que es la expresión que representa el segundo argumento de ChangeType (me tomó un tiempo para darse cuenta de que esto es una Sub método de Sonic), que parece ser un Type (no se puede ver el código, pero yo creo que es una suposición razonable!).

Se cuece en la expresión como una ConstantExpression de una instancia de Type. No pregunto cómo iba reduciendo el parámetro - un montón de pila que se arrastran y el trabajo reflector;)

Como se mencionó en la primera mitad de mi respuesta, es difícil ver cómo el código que la expresión del árbol usos compilador siempre puede crear un MethodAccessException, ya que siempre está accediendo a la ctor pública del tipo StrongBox<T>.

Sin embargo, se molestaría si el tipo pasa como el genérico no es público. "Pero espera," usted dice, "Type es público!".

Eso podría ser, pero la instancia Type devuelto en tiempo de ejecución de typeof() o GetType() no es - que es una instancia de RuntimeType - que es interno

.

¿Cuál es la razón por el fragmento de código anterior también se disparará el mismo error.

La solución

Cambiar el código que produce el argumento Type para ChangeType(,) de

Expression.Constant([type])

(que voy a casi garantía de que se trata por el momento) a

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

Estos trabajos, porque estás diciendo explícitamente al compilador que utilice el Type pública para la constante, en lugar del tipo reflejada de RuntimeType.

Se puede probar esta solución aplicándolo a mi código de ejemplo en el bloque anterior y volver a ejecutar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top