Expression .Compile in Medium Trust-Umgebung
-
02-10-2019 - |
Frage
Beim Versuch, einen Ausdruck in einem App Medium Vertrauen Web zu kompilieren Ich erhalte eine Method. Kennt jemand einen anderen Weg, um einen Ausdruck unter mittlerer Vertrauenswürdigkeit oder eine Abhilfe zu kompilieren, diese Ausnahme zu vermeiden?
Der Code, der die Ausnahme auslöst:
Expression<Func<object>> efn =
Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));
Func<object> fn = efn.Compile(); // Exception thrown here
Die Variable Plan ist ein Ausdruck, der die folgenden Ausführungsplan darstellt:
{
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 [] {}
)
}
Der vollständige 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)
Lösung
Das zugrunde liegende Problem ist, dass die Art zu System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
weitergegeben wird entweder nicht öffentlich, oder einen Konstruktor hat, der nicht öffentlich ist.
- angesichts der Einfachheit des Codes Beispiels im Vergleich zu der Tiefe des Stacktrace ich das Problem liegt nicht in plan
glauben, aber in einem Ausdruck innerhalb plan
(da Sie in Ihrem Kommentar auf Marcs Antwort sagen, dass es auch ein Ausdruck) dass Referenzen der Typ, der dann beschränkt ist.
Der Ausdruck, der die Quelle des Fehlers ist hier ein ConstantExpression
, die von dem geschützten Typ sein muss.
Die einzige verwirrende Sache über dieses ist jedoch, dass die Art Argument, dass AddGlobal
zu Activator.CreateInstance
geht StrongBox<T>
ist, die Öffentlichkeit und hat einen öffentlichen Konstruktor -. Was bedeuten würde, dass dieser Fehler nicht möglich sein sollte,
Vielleicht aber es ist etwas versteckt mit StrongBox<T>
verbunden, dass wir nicht durch Reflector sehen können.
Also, ich würde auf dem ganzen Ausdrucksbaum von plan
dargestellt werden Suche und Prüfung aller in ConstantExpression
s referenzierten Typen zu gewährleisten, dass sie alle zugänglich sind. Wenn nach tun, dass alle Arten zugänglich gezeigt werden, sind immer noch dieser Fehler auftritt, dann könnte es ein Bug im Rahmen sein.
Allerdings - ich hätte gedacht, dass ein solcher Fehler bereits als ConstantExpression
für etwas so einfach gefunden habe würde
EDIT (Ersetzen Zurück Edit) mit der Antwort
Ich habe es, und es ist ein sehr kleines Problem. Sie können mit diesem kleinen Stück Code in einer aspx Seite reproduzieren, die in mittlerer Vertrauenswürdigkeit ausgeführt wird, ist:
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());
Also, in dem Code, den Sie zur Verfügung gestellt haben, dann ist es der Ausdruck das zweite Argument zu ChangeType
darstellt (ich brauchte eine Weile zu erkennen, dass das ist ein Sub Sonic-Verfahren), das eine Type
zu sein scheint (kann das nicht sehen Code, aber ich denke, es ist eine vernünftige Vermutung!).
Es ist im Ausdruck als ConstantExpression
einer Type
Instanz gebacken. Fragen Sie nicht, wie ich auf der Parameter verengt - viele Stapel kriechenden und Reflektor Arbeit;)
Wie in der ersten Hälfte meiner Antwort erwähnt, ist es schwierig zu sehen, wie der Code, dass die Expression Baum-Compiler verwendet jemals eine Method erstellen, da es sich immer die Öffentlichkeit Ctor des StrongBox<T>
Typ Zugriff.
Allerdings wäre es aufregen, wenn der Typ in geben als die generische nicht öffentlich ist. "Aber warten Sie," Sie sagen: "Type
Öffentlichkeit ist".
Das könnte sein, aber die Type
Instanz zur Laufzeit aus typeof()
oder GetType()
zurückgegeben wird, ist nicht - es ist eine Instanz von RuntimeType
- das ist interne
Welche ist auch, warum der obige Codeausschnitt wird auch die gleichen Fehler auslösen.
Das Update
Ändern Sie den Code, der die Type
Argument für ChangeType(,)
von
Expression.Constant([type])
(was ich werde fast garantieren, dass es im Moment) zu
Expression.Constant([type], typeof(Type))
Das funktioniert, weil Sie explizit die Compiler zu sagen, die Öffentlichkeit Type
für die Konstante zu verwenden, anstelle der reflektierten Art von RuntimeType
.
Sie können dieses Update testen, indem Sie es zu meinem Beispielcode in dem vorherigen Block und die Anwendung erneut ausgeführt wird.