سؤال

عند محاولة تجميع تعبير في تطبيق ويب متوسطة الثقة ، أحصل على 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) إما ليس عاما ، أو لديه مُنشئ غير عام.

الآن - بالنظر إلى بساطة مثال الكود الخاص بك مقابل عمق StackTrace ، أعتقد أن المشكلة لا تكمن في plan, ، ولكن في تعبير داخل plan (بما أنك تقول في تعليقك على إجابة مارك بأنه أيضًا تعبير) يشير إلى النوع الذي يتم تقييده بعد ذلك.

التعبير الذي هو مصدر الخطأ هنا هو ConstantExpression الذي يجب أن يكون من النوع المقيد.

ومع ذلك ، فإن الشيء المربك الوحيد في هذا الأمر هو أن الحجة النوع AddGlobal يمر إلى Activator.CreateInstance هو StrongBox<T>, ، وهو عام وله مُنشئ عام - مما يعني أن هذا الخطأ يجب أن يكون مستحيلًا.

ربما ، ومع ذلك ، هناك شيء مخفي مرتبط به StrongBox<T> أننا لا نستطيع أن نرى من خلال العاكس.

لذا ، سأبحث في شجرة التعبير بأكملها ممثلة بـ plan وفحص جميع الأنواع المشار إليها في ConstantExpressionS للتأكد من أنها يمكن الوصول إليها جميعًا. إذا كان من الممكن الوصول إلى جميع الأنواع ، فلا يزال هذا الخطأ يحدث ، فقد يكون هذا خطأ في الإطار.

ومع ذلك - كنت أعتقد أن مثل هذا الخطأ قد تم العثور عليه بالفعل لشيء بسيط مثل أ 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 نموذج. لا تسأل كيف ضاقت المعلمة - الكثير من زحف المكدس والعمل العاكس ؛)

كما هو مذكور في النصف الأول من إجابتي ، من الصعب أن نرى كيف يمكن للرمز الذي يستخدمه برنامج التحويل البرمجي التعبير إنشاء طريقة AccessException ، لأنه دائمًا ما يصل إلى CTOR العام لـ StrongBox<T> يكتب.

ومع ذلك ، سوف ينزعج إذا تم تمرير النوع لأن عام ليس عامًا. "لكن انتظر ،" أنت تقول ، "Type هو العام! ".

قد يكون ذلك ، لكن Type عاد مثيل في وقت التشغيل من typeof() أو GetType() ليس - إنه مثال RuntimeType - الذي داخلي.

وهذا هو السبب أيضًا في أن قصاصة الكود أعلاه ستؤدي أيضًا إلى نفس الخطأ.

المأزق

تغيير الرمز الذي ينتج Type حجة ل ChangeType(,) من

Expression.Constant([type])

(الذي سأضمنه تقريبًا في الوقت الحالي)

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

هذا يعمل ، لأنك تخبر المترجم بشكل صريح باستخدام الجمهور Type للثابت ، بدلاً من النوع المنعكس من RuntimeType.

يمكنك اختبار هذا الإصلاح عن طريق تطبيقه على رمز المثال الخاص بي في الكتلة السابقة وإعادة التشغيل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top