表达式。在中等信任环境中编译

当尝试在中型信任Web应用程序中编译表达式时,我得到一个MethodAccessException。 有没有人知道在中等信任下编译表达式的另一种方法或解决方法以避免此exception?

抛出exception的代码:

Expression<Func> efn = Expression.Lambda<Func>(Expression.Convert((plan,typeof(object))); Func 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) 

这里的根本问题是传递给System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)要么不公开,要么具有构造函数不公开。

现在 – 考虑到代码示例的简单性与堆栈跟踪的深度,我认为问题不在于plan ,而在于plan中的表达式(因为您在Marc的回答中说它也是表达式),它引用了然后限制的类型。

这里作为错误源的表达式是ConstantExpression ,它必须是受限制的类型。

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

但是,也许有一些与StrongBox相关的隐藏,我们无法通过Reflector看到。

因此,我将查看由plan表示的整个表达式树,并检查ConstantExpression引用的所有类型,以确保它们都可访问。 如果在执行此操作后显示所有类型都可访问,则仍会出现此错误,然后它可能是框架中的错误。

但是 – 我会认为已经发现了一个像ConstantExpression这样简单的bug!

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

我知道了,这是一个非常微妙的问题。 您可以在配置为以中等信任方式运行的aspx页面中使用这些小代码重现:

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

所以,在你提供的代码中,它是表示ChangeType的第二个参数的表达式(花了一些时间才意识到这是一个Sub Sonic方法),它似乎是一个Type (看不到代码但是我认为这是一个合理的猜测!)。

它在表达式中作为Type实例的ConstantExpression进行烘焙。 不要问我如何缩小参数 – 大量的堆栈爬行和reflection器工作;)

正如我在答案的前半部分所提到的,很难看出Expression Tree编译器使用的代码如何创建一个MethodAccessException,因为它总是访问StrongBox类型的公共ctor。

但是,如果作为generics传入的类型不公开,则会感到不安。 “但是等等,”你说,“ Type是公开的!”。

那可能是,但是在运行时从typeof()GetType()返回的Type实例不是 – 它是RuntimeType的一个实例 – 它是内部的

这也是为什么上面的代码片段也会触发相同的错误。

修复

更改为ChangeType(,)生成Type参数的代码

 Expression.Constant([type]) 

(我几乎可以保证它现在正好)

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

这是有效的,因为您明确告诉编译器使用公共Type作为常量,而不是reflection类型的RuntimeType

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