الصعوبات المفقودة في الأسلوب في C # 4.0: ديناميكية مقابل RealProxy

StackOverflow https://stackoverflow.com/questions/961673

سؤال

هل يعرف أحد وسيلة لاعتراض dynamic مكالمات الأسلوب (خاصة تلك التي سترفع RuntimeBinderExceptionق) مع RealProxyب كنت آمل أن أتخلص من الاستثناء وتنفيذ "الطريقة المفقودة" علاوة على ذلك، ولكن يبدو أنه يتم إلقاؤه قبل أن يحصل اعتراضي على مظهر.

بلدي الاختبار يبدو فقط:

dynamic hello = MethodMissingInterceptor<DynamicObject>.Create();
Assert.AreEqual("World", hello.World());

أين World لم تنفذ فعلا على DynamicObject. وبعد يعد اعتراضا واضحا جدا - كنت آمل أن تحقق IMethodReturnMessage.Exception بالنسبة RuntimeBinderException وإلى الأمام إلى شيء مثل:

public IMessage MethodMissing(IMethodCallMessage call)
{
    return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call);
}

لسوء الحظ، كل ما أراه في اعتراضي هو بعض المكالمات GetType, وليس غير موجود World طريقة.

فشل ذلك - هل يعرف أحد إذا كان هناك DynamicProxy الإصدار قيد التشغيل بسعادة على .NET 4.0 حتى الآن قد يكون قد تناول المشكلة؟

هل كانت مفيدة؟

المحلول

سأبدأ بالإجابة الطويلة. كل ربط عملية ديناميكية في C # هل هذه الأشياء الثلاثة تقريبا في هذا الترتيب:

  1. اطلب من الكائن أن يربط نفسه إذا كان ينفذ IdynamicmetaObjectProvider أو كائن COM، وإذا فشل ذلك، ثم ...
  2. ربط العملية بعملية حول كائن CLR عادي باستخدام التفكير، وإذا فشل ذلك، ثم ...
  3. إرجاع DynamicmetaObject الذي يمثل فشل إجمالي الربط.

أنت ترى مكالمات GetTyPE لأنه في الخطوة 2، يعكس Binder C # Runtime Binder فوقك لمحاولة معرفة ما إذا كان لديك طريقة "عالمية" مناسبة للاتصال بها، وهذا يحدث لأن تنفيذ IdynamicmetaobjectProvider في Hello، إذا كان هناك واحد، لا يمكن أن يأتي مع أي شيء خاص للقيام به.

لسوء الحظ بالنسبة لك، بحلول الوقت الذي يتم فيه طرح RuntimeBinderException، لم نعد ملزمة. يستخرج الاستثناء من مرحلة التنفيذ من العملية الديناميكية، استجابة لكائن التعريف الذي تم إرجاعه بسبب الخطوة 3. الفرصة الوحيدة لك للقبض عليها في موقع الاتصال الفعلي.

بحيث لن تنجح هذه الاستراتيجية لك إذا كنت ترغب في تنفيذ method_missing في C #. لديك بعض الخيارات رغم ذلك.

أحد الخيارات السهلة هو تطبيق idynamicmicmetaobjectprovider في MethoneMissmissingingErTecor، وتأجيل تنفيذ IDMOP للكائن الملتفوف. في حالة الفشل في جزء من IDMOP الداخلي، يمكنك ربط كل ما تريد (ربما مكالمة إلى مندوب المناثر المخزنة في اعتراضي). الجانب السلبي هنا هو أن هذا يعمل فقط للأشياء المعروفة بأنها كائنات ديناميكية، مثل تلك التي تنفذ IDMOP للبدء بها. هذا لأنك تدرج بشكل أساسي نفسك بين الخطوات 1 و 2.

بديل آخر يمكنني التفكير فيه هو تطبيق IdynamicmicmetaoBjectRPovider، وفي ذلك، استجابة إيجابية لكل ربط، وإرجاع مكالمة إلى طريقة (أ) تنتج نفس التعليمات البرمجية التي ستنتج فيها C # مترجمها للربط في المقام الأول، و ( ب) يمسك RuntimeBinderException للاتصال بطريقة طريقة. الجانب السلبي هنا هو أنه سيكون معقدا جدا - كنت بحاجة إلى توليد أنواع مفوضا تعسفيا و IL التي تستخدمها، ضد الأنواع العامة في جمعية Binder وقت التشغيل C #، بصراحة، ليست مخصصة للاستهلاك العام. ولكن على الأقل ستحصل على طريقة مفقودة ضد جميع العمليات.

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

جوهر المشكلة هنا هو أن C # 4.0 ليس لديه تصميم يتوقع رغبتك في القيام بذلك. على وجه التحديد، لا يمكنك إدخال نفسك بسهولة بين الخطوتين 2 و 3. ينقلني إلى الإجابة القصيرة، والذي آسف، C # 4.0 لا يحتوي على method_missing.

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