表达式.在中等信任环境中编译
当尝试在中等信任度 Web 应用程序中编译表达式时,我收到 MethodAccessException。 有谁知道在中等信任度下编译表达式的另一种方法或避免此异常的解决方法?
抛出异常的代码:
Expression<Func<object>> efn =
Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));
Func<object> fn = efn.Compile(); // Exception thrown here
变量 plan 是一个表达式,表示以下执行计划:
{
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)
When trying to compile an Expression in a medium trust web app I'm getting a MethodAccessException.
Does anyone know of another way to compile an expression under medium trust or a workaround to avoid this exception?
The code that throws the exception:
Expression<Func<object>> efn =
Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));
Func<object> fn = efn.Compile(); // Exception thrown here
The variable plan is an Expression that represents the following execution plan:
{
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 [] {}
)
}
The full stack trace:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的根本问题是传递给 System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binderinder, Object[] args, CultureInfoculture, Object[]activationAttributes) 的类型不是公共的,或者有一个非公开的构造函数。
现在 - 考虑到您的代码示例的简单性与堆栈跟踪的深度,我相信问题不在于
plan
,而是在于plan
中的表达式(因为您在对 Marc 的回答的评论(它也是一个表达式)引用了随后受到限制的类型。这里的错误源表达式是一个
ConstantExpression
,它必须是受限类型。然而,唯一令人困惑的事情是
AddGlobal
传递给Activator.CreateInstance
的类型参数是StrongBox
,即public 并且有一个公共构造函数 - 这意味着这个错误应该是不可能的。然而,也许有一些与
StrongBox
相关的隐藏内容我们无法通过 Reflector 看到。因此,我将查看由 plan 表示的整个表达式树,并检查 ConstantExpression 中引用的所有类型以确保它们都是可访问的。如果执行此操作后所有类型都显示为可访问,但仍然出现此错误,则可能是框架中的错误。
然而 - 我本以为像
ConstantExpression
这样简单的东西就已经被发现了!编辑(替换以前的编辑)有了答案
我已经明白了,这是一个非常微妙的问题。您可以在配置为以中等信任度运行的 aspx 页面中使用这一点代码进行重现:
因此,在您提供的代码中,它是表示
ChangeType
的第二个参数的表达式(采用我花了一段时间才意识到这是一个 Sub Sonic 方法),它似乎是一个Type
(看不到代码,但我认为这是一个合理的猜测!)。它作为
Type
实例的ConstantExpression
嵌入到表达式中。不要问我如何缩小参数范围 - 大量堆栈爬行和反射器工作;)正如我的答案的前半部分所提到的,很难看出表达式树编译器使用的代码如何创建 MethodAccessException,因为它始终访问
StrongBox
类型的公共构造函数。然而,如果作为泛型传入的类型不是公共的,它会感到不安。 “但是等等,”你说,“
Type
是公开的!”。可能是这样,但运行时从
typeof()
或GetType()
返回的Type
实例不是 - 它是的实例>RuntimeType
- 这是内部。这也是为什么上面的代码片段也会触发相同的错误。
修复
更改为
ChangeType(,)
生成Type
参数的代码(我几乎可以保证它现在是这样的) )
这有效,因为您明确告诉编译器使用公共
Type
作为常量,而不是RuntimeType
的反射类型。您可以通过将其应用于上一个块中的示例代码并重新运行来测试此修复。
The underlying problem here is that the type being passed to
System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
is either not public, or has a constructor that is not public.Now - given the simplicity of your code example versus the depth of the stacktrace I believe the problem lies not in
plan
, but in an expression withinplan
(since you say in your comment on Marc's answer that it is also an expression) that references the type which is then restricted.The expression that is the source of the error here is a
ConstantExpression
which must be of the restricted type.The only confusing thing about this, however, is that the type argument that
AddGlobal
passes toActivator.CreateInstance
isStrongBox<T>
, which is public and has a public constructor - which would imply that this error should be impossible.Perhaps, however, there is something hidden associated with
StrongBox<T>
that we can't see through Reflector.So, I would be looking at the whole expression tree represented by
plan
and examining all the types referenced inConstantExpression
s to ensure they are all accessible. If after doing that all types are shown to be accessible, this error still occurs then it could be a bug in the framework.However - I would have thought that such a bug would've been found already for something as simple as a
ConstantExpression
!EDIT (Replacing Previous Edit) WITH THE ANSWER
I've got it, and it's a very subtle problem. You can reproduce with this little bit of code in an aspx page that is configured to run in medium trust:
So, in the code you've provided, it's the expression representing the second argument to
ChangeType
(took me a while to realise that that is a Sub Sonic method), which appears to be aType
(can't see the code but I think it's a reasonable guess!).It's baked in the expression as a
ConstantExpression
of aType
instance. Don't ask how I narrowed down the parameter - lots of stack crawling and reflector work ;)As mentioned in the first half of my answer, it's difficult to see how the code that the Expression Tree compiler uses can ever create a MethodAccessException, since it's always accessing the public ctor of the
StrongBox<T>
type.However, it would get upset if the type passed in as the generic is not public. "But wait," you say, "
Type
is public!".That might be, but the
Type
instance returned at runtime fromtypeof()
orGetType()
isn't - it's an instance ofRuntimeType
- which is internal.Which is also why the above code snippet will also trigger the same error.
The fix
Change the code that produces the
Type
argument forChangeType(,)
from(which I'll almost guarantee that it is at the moment) to
This works, because you're explicitly telling the compiler to use the public
Type
for the constant, instead of the reflected type ofRuntimeType
.You can test this fix by applying it to my example code in the previous block and re-running.