表达式 .compile在中等信任环境中
-
02-10-2019 - |
题
在尝试在Medium Trust 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)
解决方案
这里的根本问题是传递给 System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
要么不是公开,要么具有不公开的构造函数。
现在 - 鉴于您的代码示例的简单性与堆栈深度的深度,我认为问题不在 plan
, ,但在内部的表达中 plan
(因为您在对Marc的答案的评论中说,这也是一种表达式)引用了然后被限制的类型。
这里是错误源的表达式是 ConstantExpression
这必须是受限类型。
然而,唯一令人困惑的事情是类型的参数 AddGlobal
传递 Activator.CreateInstance
是 StrongBox<T>
, ,这是公开的,并具有公共构造函数 - 这意味着该错误应该是不可能的。
但是,也许与 StrongBox<T>
我们看不到反射器。
因此,我会看着由代表的整个表达树 plan
并检查所有引用的类型 ConstantExpression
s确保它们都可以访问。如果这样做后,所有类型都可以访问,则此错误仍会发生,那么它可能是框架中的错误。
但是 - 我本来会认为,这样的错误已经被发现了 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
(花了我一段时间才意识到那是一种亚音话),这似乎是 Type
(看不到代码,但我认为这是一个合理的猜测!)。
它在表达中被烤出来 ConstantExpression
一个 Type
实例。不要问我如何缩小参数 - 很多堆栈爬行和反射器工作;)
正如我答案的上半部分所述,很难看到表达式树编译器使用的代码如何创建MethodAccessexception,因为它始终访问其公共ctor StrongBox<T>
类型。
但是,如果通用不公开的类型通过,那将会感到不安。 “但是等等,”你说,”Type
是公共的!”。
可能是,但是 Type
实例从运行时返回 typeof()
或者 GetType()
不是 - 这是一个实例 RuntimeType
- 是 内部的.
这也是为什么上述代码段也会触发相同错误的原因。
修复
更改产生的代码 Type
争论 ChangeType(,)
从
Expression.Constant([type])
(我几乎保证目前是)
Expression.Constant([type], typeof(Type))
这起作用,因为您明确地告诉编译器使用公众 Type
对于常数,而不是反映的类型 RuntimeType
.
您可以通过将其应用于上一个块并重新运行的示例代码来测试此修复程序。