كيفية إلقاء الكائنات التي تم إنشاؤها من خلال الانعكاس بشكل صحيح

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

  •  09-06-2019
  •  | 
  •  

سؤال

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

باستخدام الانعكاس، كنت أرغب في تكرار الأنواع الموجودة داخل ملف تنفيذ البرنامج الإضافي الخاص بي وإنشاء مثيلات للأنواع.لقد تمكنت من إنشاء مثيل للفئات بنجاح باستخدام هذا الرمز، لكن لم أتمكن من إرسال الكائن الذي تم إنشاؤه إلى الواجهة.

لقد جربت هذا الرمز ولكن لم أتمكن من إرسال الكائن كما توقعت.لقد قمت بتنفيذ العملية باستخدام مصحح الأخطاء وتم استدعاء المنشئ المناسب.أظهر لي كائن Quickwatching أنه يحتوي على الحقول والخصائص التي توقعت رؤيتها في فئة التنفيذ.

loop through assemblies
  loop through types in assembly
    // Filter out unwanted types
    if (!type.IsClass || type.IsNotPublic || type.IsAbstract )
      continue;
    // This successfully created the right object
    object o = Activator.CreateInstance(type);
    // This threw an Invalid Cast Exception or returned null for an "as" cast
    // even though the object implemented IPlugin      
    IPlugin i = (IPlugin) o;

لقد جعلت الكود يعمل مع هذا.

using System.Runtime.Remoting;
ObjectHandle oh = Activator.CreateInstance(assembly.FullName, type.FullName);
// This worked as I intended
IPlugin i = (IPlugin) oh.Unwrap();
i.DoStuff();

وهنا أسئلتي:

  1. يقوم Activator.CreateInstance(Type t) بإرجاع كائن، لكن لم أتمكن من إرسال الكائن إلى الواجهة التي قام الكائن بتنفيذها.لماذا؟
  2. هل كان يجب علي استخدام حمل زائد مختلف لـ CreateInstance()؟
  3. ما هي النصائح والحيل المتعلقة بالانعكاس؟
  4. هل هناك جزء مهم من التفكير لا أفهمه؟
هل كانت مفيدة؟

المحلول

أنا فقط أخمن هنا لأنه من التعليمات البرمجية الخاصة بك ليس من الواضح أين لديك تعريف لواجهة IPlugin ولكن إذا لم تتمكن من إرسال التطبيق المضيف الخاص بك، فمن المحتمل أن يكون لديك واجهة IPlugin في التجميع المضيف الخاص بك ثم في نفس الوقت تجميع البرنامج المساعد الخاص بك.هذا لن ينجح.

أسهل شيء هو إنجاز هذا العمل هو وضع علامة على واجهة IPlugin كواجهة عامة في التجميع المضيف الخاص بك ثم الحصول على تجميع البرنامج الإضافي الخاص بك تجميع تطبيق المضيف المرجعي, ، لذلك يمكن لكلا المجمعين الوصول إليه نفس الواجهة.

نصائح أخرى

أمم...إذا كنت تستخدم Assembly.LoadFrom لتحميل التجميع الخاص بك، فحاول تغييره Assembly.LoadFile بدلاً من ذلك.

عملت بالنسبة لي

من هنا: http://www.eggheadcafe.com/community/aspnet/2/10036776/solution-found.aspx

@لوبوس هاسكو

لقد سمّرته على الأنف.يحتوي تصميمي الأصلي على ثلاث مجموعات مختلفة مع كل من المضيف والمكون الإضافي الذي يشير إلى مجموعة واجهة البرنامج المساعد.

لقد جربت حلاً منفصلاً مع تنفيذ المضيف وتجميع الواجهة وتجميع تنفيذ البرنامج المساعد.ضمن هذا الحل، عملت التعليمات البرمجية الموجودة في الكتلة الأولى كما هو متوقع.

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

كنت أحاول حل هذا الأمر بنفسي وتمكنت من العثور على الإجابة!

كان لدي 3 مشاريع مختلفة في C#

  • أ - مشروع واجهة البرنامج المساعد
  • ب - مشروع استضافة exe -> المراجع أ
  • ج - مشروع تنفيذ البرنامج المساعد -> المراجع أ

لقد كنت أتلقى خطأ الإرسال أيضًا حتى قمت بتغيير اسم التجميع لمشروع Plugin Interface الخاص بي ليطابق مساحة الاسم التي كنت أحاول الإرسال إليها.

على سبيل المثال.

IPluginModule pluginModule = (IPluginModule)Activator.CreateInstance(curType);

كان فاشلاً لأن التجميع الذي تم تعريف واجهة IPluginModule فيه كان يسمى "Common"، لكن -type- الذي كنت أقوم بالإرسال إليه كان "Blah.Plugins.Common.IPluginModule".

لقد قمت بتغيير اسم التجميع لمشروع الواجهة ليصبح "Blah.Plugins.Common" مما يعني نجاح عملية التمثيل.

نأمل أن يساعد هذا التفسير شخص ما.نرجع للكود..

هل النوع الخاص بك ليس عامًا، إذا كان الأمر كذلك، فاستدعاء التحميل الزائد الذي يأخذ قيمة منطقية:

Activator.CreateInstance(type, true);

أيضًا، في المثال الأول، تأكد مما إذا كان o فارغًا، وإذا لم يكن كذلك، فاطبع o.GetType().Name لترى ما هو عليه حقًا.

@اخترق

حاولت أن أبقي الكود الزائف بسيطًا.يشغل foreach مساحة كبيرة وأقواسًا.لقد أوضحت ذلك.

o.GetType().FullName يُرجع Plugins.Multiply وهو الكائن المتوقع.يقوم Plugins.Multiply بتنفيذ IPlugin.لقد مررت بهذه العملية في مصحح الأخطاء عدة مرات حتى استسلمت للمساء.لم أتمكن من معرفة سبب عدم قدرتي على الإدلاء بها لأنني شاهدت عمال البناء وهم يطلقون النار حتى أصبحت غاضبًا من الفوضى برمتها.عدت إليه هذا المساء وعملت عليه، لكني ما زلت لا أفهم سبب فشل فريق التمثيل في مجموعة التعليمات البرمجية الأولى.تعمل كتلة التعليمات البرمجية الثانية، لكنها تبدو غير مريحة بالنسبة لي.

الرابط إلى المثقف أعلاه هو الحل الرئيسي لمشكلة استخدام Assembly.LoadFile() بدلاً من .LoadFrom()

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