代码之家  ›  专栏  ›  技术社区  ›  Adam Cooper

expression<tdelegate>。在中等信任环境中编译

  •  9
  • Adam Cooper  · 技术社区  · 14 年前

    当尝试在中等信任度的Web应用程序中编译表达式时,我得到了一个methodAccessException。 是否有人知道在中等信任下编译表达式的另一种方法,或避免这种异常的变通方法?

    引发异常的代码:

    Expression<Func<object>> efn = 
      Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));
    
    Func<object> fn = efn.Compile(); // Exception thrown here
    

    变量计划是表示以下执行计划的表达式:

    {
      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)
    
    1 回复  |  直到 12 年前
        1
  •  15
  •   Andras Zoltan    12 年前

    这里的基础问题是要传递给的类型 System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) 不是公共的,或者具有非公共的构造函数。

    现在-考虑到代码示例的简单性和stacktrace的深度,我认为问题不在 plan ,但在表达式中 计划 (因为你在对马克的回答的评论中说这也是一个表达方式),它引用了当时被限制的类型。

    这里的错误源表达式是 ConstantExpression 必须是受限类型。

    然而,唯一令人困惑的是,类型参数 AddGlobal 传到 Activator.CreateInstance StrongBox<T> ,它是公共的,并且有一个公共的构造函数-这意味着这个错误是不可能的。

    然而,也许有一些隐藏的东西与 strongBox<t> 我们无法透过反射镜看到。

    所以,我将看到整个表达式树 计划 并检查中引用的所有类型 恒压 以确保它们都是可访问的。如果在这样做之后,所有类型都显示为可访问,那么这个错误仍然会发生,那么它可能是框架中的一个bug。

    但是-我本以为这样的一个bug已经被发现了 恒压 !

    编辑(替换以前的编辑) 带着答案

    我明白了,这是个非常微妙的问题。您可以在配置为在中级信任下运行的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());
    

    因此,在您提供的代码中,它是表示 ChangeType (花了我一段时间才意识到这是一种亚音速方法),这似乎是 Type (看不到代码,但我认为这是合理的猜测!).

    它在表达中被烤成 恒压 A的 类型 实例。不要问我是如何缩小参数范围的-很多堆栈爬行和反射器工作;)

    正如我在回答的前半部分中提到的,很难看到表达式树编译器使用的代码如何创建methodAccessException,因为它总是访问 strongBox<t> 类型。

    但是,如果作为泛型传入的类型不是公共的,则会很不高兴。”但是等等,“你说,” 类型 是公开的!”.

    可能是,但是 类型 运行时从返回的实例 typeof() GetType() 不是吗?这是 RuntimeType -这是 内部的 .

    这也是上面的代码片段也会触发相同错误的原因。

    修复

    更改生成 类型 论证 ChangeType(,)

    Expression.Constant([type])
    

    (我几乎可以保证现在是这样)

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

    这是可行的,因为您显式地告诉编译器使用公共的 类型 对于常量,而不是 运行时间表 .

    您可以通过将其应用于上一个块中的示例代码并重新运行来测试此修复程序。