2010-07-07 14 views
9

Beim Versuch, einen Ausdruck in einer vertrauenswürdigen Webanwendung zu kompilieren, erhalte ich eine MethodAccessException. Kennt jemand eine andere Möglichkeit, einen Ausdruck unter mittlerer Vertrauenswürdigkeit oder eine Problemumgehung zu kompilieren, um diese Ausnahme zu vermeiden?Ausdruck <TDelegate> .Compile in Medium Trust-Umgebung

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 

Der 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) 
+1

Sie verfügen nicht über die ReflectionPermission (ReflectionPermissionFlag.MemberAccess), um auf nicht öffentliche Member zuzugreifen. –

+0

@ Jaroslav - Ich weiß, das ist die Ursache für den Fehler Ich versuche herauszufinden, was es ist, dass diese Erlaubnis erfordert und wie man sie umgehen kann, wenn das möglich ist. –

+1

@Adam: Wenn Sie nicht-öffentliche Mitglieder (Eigenschaften, Felder, Methoden, Konstruktoren) verwenden, versuchen Sie es ohne sie (wenn Sie können). Selbst externe Parameter können ein solches Verhalten verursachen. Versuchen Sie, sich um die verwendeten Klassen zu "reflektieren" ... –

Antwort

15

Das zugrunde liegende Problem ist, dass der Typ anübergeben wird 0 ist entweder nicht öffentlich oder hat einen Konstruktor, der nicht öffentlich ist.

jetzt - angesichts der Einfachheit des Codes Beispiels im Vergleich zu der Tiefe des stacktrace ich glaube, das Problem liegt nicht in plan, sondern in einem Ausdruck innerhalb plan (da Sie in Ihrem Kommentar sagen auf Marcs Antwort, dass es auch ein Ausdruck), die auf den Typ verweist, der dann eingeschränkt ist.

Der Ausdruck, der hier die Fehlerquelle ist, ist ein ConstantExpression, der vom eingeschränkten Typ sein muss.

Die einzige verwirrende Sache über dieses ist jedoch, dass die Art Argument, dass AddGlobal-Activator.CreateInstance geht StrongBox<T> ist, die Öffentlichkeit und hat einen öffentlichen Konstruktor - das, dass dieser Fehler unmöglich sein würde bedeuten sollte.

Vielleicht ist jedoch etwas mit StrongBox<T> verborgen, das wir nicht durch Reflektor sehen können.

Also würde ich den gesamten Ausdrucksbaum, dargestellt durch plan, betrachten und alle Typen untersuchen, auf die in ConstantExpression s verwiesen wird, um sicherzustellen, dass sie alle zugänglich sind. Wenn nach diesem Vorgang gezeigt wird, dass alle Typen verfügbar sind, tritt dieser Fehler immer noch auf, dann könnte es sich um einen Fehler im Framework handeln.

Allerdings - ich hätte gedacht, dass ein solcher Fehler schon für etwas so einfaches wie ein ConstantExpression gefunden worden wäre!

EDIT (Ersetzen Zurück Edit) MIT DER ANTWORT

Ich habe es habe, und es ist ein sehr kleines Problem. Sie können mit diesem kleinen Stück Code in einer aspx Seite zu 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 haben zur Verfügung gestellt, es ist der Ausdruck, die das zweite Argument ChangeType (nahm mir eine Weile, um zu erkennen, dass das eine Subsonic-Methode ist), die eine Type zu sein scheint (kann den Code nicht sehen, aber ich denke, es ist eine vernünftige Schätzung!).

Es ist im Ausdruck als ConstantExpression einer Type Instanz gebacken.Fragen Sie nicht, wie ich den Parameter eingegrenzt habe - viele Stack-Crawler und Reflektoren;)

Wie in der ersten Hälfte meiner Antwort erwähnt, ist es schwierig zu sehen, wie der Code, den der Expression Tree Compiler verwendet, jemals erstellt werden kann eine MethodAccessException, da immer auf den öffentlichen ctor des Typs StrongBox<T> zugegriffen wird.

Allerdings würde es sich aufregen, wenn der Typ, der als generisch übergeben wurde, nicht öffentlich ist. "Aber warte", sagst du, "Type ist öffentlich!".

das sein könnte, aber die Type Instanz zurückgegeben zur Laufzeit aus typeof() oder GetType() ist nicht - es ist eine Instanz von RuntimeType - die internen ist.

Aus diesem Grund wird das obige Code-Snippet auch den gleichen Fehler auslösen.

Das Update

Ändern Sie den Code, der die Type Argument für ChangeType(,) von

Expression.Constant([type]) 

(was ich fast garantieren, dass es im Moment ist) zu

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

Das funktioniert, weil Sie dem Compiler explizit mitteilen, das öffentlichezu verwendenfür die Konstante, anstelle des reflektierten Typs RuntimeType.

Sie können dieses Update testen, indem Sie es auf meinen Beispielcode im vorherigen Block anwenden und erneut ausführen.

+0

Danke, das ist wirklich hilfreich, hast du irgendwelche Vorschläge für einen schnellen Weg, die nicht zugänglichen Typen aufzuspüren? Ich bin ziemlich sicher, dass dies kein Framework-Bug ist, aber ich finde, dass die genaue Ursache eine bedeutende Herausforderung ist. –

+0

Hmmm ... nun, ich dachte darüber nach, wie du das machen könntest. Vielleicht können Sie einen Ausdruck visitor verwenden, der nach "ConstantExpression" sucht, dessen Typ entweder nicht öffentlich ist oder der mindestens einen nicht öffentlichen Konstruktor hat - der ihn eingrenzen sollte. MSDN hat eine Verknüpfung zu einem Beispielausdruck-Besucher. Ich werde es mir ansehen und es auf die Antwort setzen. –

+0

@Adam - Ich habe meine Antwort mit einem Code aktualisiert, der Ihnen bei der Diagnose helfen könnte, neben dem Link von der MSDN, die Sie für einen Expression Tree-Besucher benötigen. Es ist nicht perfekt - aber es sollte dich auf deinem Weg ziemlich gut ich hoffe :) –

Verwandte Themen