有人知道在中等信任或解决方法下编译表达式以避免此异常的另一种方式吗?
抛出异常的代码:
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),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,Object[] args,CultureInfo culture,Object[] activationAttributes) at System.Activator.CreateInstance(Type type,BindingFlags bindingAttr,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.GenerateConvert(ILGenerator gen,UnaryExpression u) at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen,StackType ask) at System.Linq.Expressions.ExpressionCompiler.GenerateConditional(ILGenerator gen,ConditionalExpression b) at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen,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,MemberInitExpression init) at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen,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,ReadOnlyCollection`1 args) at System.Linq.Expressions.ExpressionCompiler.GenerateNew(ILGenerator gen,NewExpression nex,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)
解决方法
现在 – 鉴于代码示例的简单性和堆栈跟踪的深度,我认为问题不在于计划中,而是在计划中的表达式中(因为您在评论Marc的答案时也表示了这一点),它引用了然后被限制的类型.
这里的错误来源的表达式是一个ConstantExpression,它必须是受限制的类型.
然而,唯一令人困惑的是,AddGlobal传递给Activator.CreateInstance的类型参数是StrongBox< T>,它是公共的,并且具有公共构造函数 – 这意味着这个错误是不可能的.
然而,也许有一些隐藏与StrongBox< T>相关联的东西.我们看不到反光板.
所以,我将查看由计划表示的整个表达式树,并检查ConstantExpressions中引用的所有类型,以确保它们都可以访问.如果在这样做之后,所有类型都被显示为可访问的,则该错误仍然发生,那么它可能是框架中的一个错误.
然而,我会认为这样的bug会被发现已经是一个简单的ConstantExpression的东西!
编辑(替换上一个编辑)与答案
我有这个,这是一个非常微妙的问题.您可以在配置为以中等信任度运行的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的第二个参数的表达式(花了我一段时间才意识到这是一个Sub Sonic方法),它似乎是一个Type(看不到代码,但是我看不到认为这是一个合理的猜测!).
它在表达式中被烘烤为Constant实例的ConstantExpression.不要问我如何缩小参数 – 大量堆栈爬行和反射器工作;)
正如我在答案的前半部分提到的那样,很难看出,表达式树编译器使用的代码如何创建一个MethodAccessException,因为它总是访问StrongBox< T>类型.
但是,如果通用类型不是公开的,那么它会感到不安. “但是等等,”你说,“类型是公开的!”
这可能是,但是在运行时从typeof()或GetType()返回的Type实例不是 – 它是RuntimeType的一个实例,它是内部的.
修复
Expression.Constant([type])
(我几乎可以保证是在这个时刻)
Expression.Constant([type],typeof(Type))
这是有效的,因为您明确地告诉编译器使用常量的公共类型,而不是RuntimeType的反映类型.
您可以通过将其应用于上一个块中的示例代码并重新运行来测试此修复程序.