سؤال

(من StockTraderRIBootstrapper.cs ملف في تطبيق مثال Prism V2 StockTrader)

ما الفرق بين هذا :

ShellPresenter presenter = new ShellPresenter();

وهذا:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • أفهم أن المثال الثاني هو التعامل مع الحاوية كمصنع، والذهاب إليها قائلًا "أحتاج إلى كائن تم إنشاء مثيل له من النوع ShellPresenter".
  • ولكن ماذا لو، على سبيل المثال؟أحتاج إلى إرسال معلمات، ما هو المعادل لـ "new ShellPresenter(1, true)" وما إلى ذلك؟
  • وبما أنه يجب إخبار الحاوية عن ShellPresenter، توقعت أن أجد في مكان ما في المشروع مكانًا يتم فيه تسجيل فئة ShellPresenter في الحاوية، على سبيل المثال.كنت أتوقع

شيء من هذا القبيل:

Container.RegisterType<IShellPresenter, ShellPresenter>();

ولكن لم تجده في أي مكان.فكيف يتعرف الحاوية على هذه الأنواع حتى يتمكن من حلها؟ لقد قمت بإعادة بناء هذا في مشروعي الخاص وحصلت على خطأ "فشل حل التبعية"., أين أحتاج لتسجيل هذه التبعية إذن؟

أي اتجاه/مناقشة هنا سيكون مفيدا.

إجابة غير مفسرة:

لذا، في برنامج التمهيد، عندما أقوم بتسجيل Shell نفسها:

protected override void ConfigureContainer()
{
    Container.RegisterType<IShellView, Shell>();
    base.ConfigureContainer();
}

ثم يمكن للحاوية حل نوع ShellPresenter.فكيف هو ShellPresenter اكتب المسجل عندما أقوم بالتسجيل صدَفَة يكتب؟

الجواب المفاجئ:

حسنًا، اتضح أنه ليس عليك تسجيل النوع الذي تحاول حله ولكن يجب عليك تسجيل أنواع المعلمات (الواجهة) التي تم تمريرها إلى مُنشئ النوع الذي تحاول حله, ، أي.منذ أن قمت بإدخال واجهة IShellView في مُنشئ ShellPresenter الخاص بي، كنت بحاجة لتسجيل نوع IShellView وليس نوع IShellPresenter:

public ShellPresenter(IShellView view) ...

لقد اختبرت هذا من خلال محاولة حل النوع اختبار:

Tester tester = Container.Resolve<Tester>();

طالما أنني أحقن SomeClass في منشئه:

public Tester(ISomeClass someClass)

أحصل على أخطاء التبعية التي لم يتم حلها حتى أقوم بالتسجيل SomeClass مع الحاوية:

Container.RegisterType<ISomeClass, SomeClass>();

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

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

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

المحلول

أنت تفهم الأساسيات.

هناك أحمال زائدة لحل الأنواع التي تتطلب وسيطات المُنشئ.وبدلاً من ذلك، يمكنك دائمًا ترميز الأنواع الخاصة بك للحصول على مُنشئ بدون معلمات.

الهدف من حاويات DI هو أنه يمكنك تكوينها لتغيير النوع الذي يتم حله لواجهة معينة دون إعادة ترجمة برنامجك.لا يمكن تغيير مثال التعليمات البرمجية الذي قدمته لتكوين الموفر في وقت التشغيل.لهذا السبب تسمح لك معظم أدوات حقن التبعيات بتكوينها في app.config/web.config/بعض ملفات التكوين الخارجية الأخرى.وبهذه الطريقة يمكنك إعادة تكوين تطبيقك لإدخال نوع مختلف دون إعادة الترجمة، وهي القوة الحقيقية لأطر عمل DI مثل Unity.

نصائح أخرى

إذا حاولت حل فئة محددة ولم تقم بتسجيل مثيل أو فئة فرعية لتلبية هذه الفئة، فسوف تقوم Unity بإنشاء مثيل للفئة المحددة لك، وحل أي تبعيات لديها.

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

حسنًا، لا يمكنني الإجابة عن Untiy، لكن بالنسبة إلى Castle Windsor، يمكن أن يكون التسجيل في ملف app.config/web.config.هناك أيضًا إمكانية إضافة المعلمات في ملف config XML.

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

في الوحدة، هناك بالفعل أ Container.RegisterType<TFrom, TTo>() مجموعة الطريقة التي تسجل الأنواع في وقت التشغيل.ربما يكون من الأكثر شيوعًا القيام بذلك باستخدام ملف تكوين XML، لكن أيًا منهما يعمل.

ومن المثير للاهتمام أنه لا يوجد في الوحدة Container.Resolve<T>(params object[] parameters) طريقة -type لحل نوع ذي قيم معلمات مُنشئة محددة.تم بناء Unity على رأس ObjectBuilder وهي مكتبة فريق P&P للقيام ببناء الكائنات وتركيبها (IIRC تمت كتابتها في الأصل لـ ObjectSpaces ولكن تم تحسينها بشكل كبير الآن).يمنحك ObjectBuilder القدرة على حقن التبعيات بطرق مختلفة، بما في ذلك عبر المنشئ، لذلك يمكنك القول - على سبيل المثال - أنك ستقوم بتمرير مثيل جديد من النوع الذي يعتمد عليه إلى مُنشئ النوع الذي تم حله؛ولكن يجب أيضًا تسجيل هذا النوع.يمكنك أيضًا تمرير مثيلات الأنواع المسجلة (مثيل مسجل / مفرد وما إلى ذلك).لكن AFAICS لا توجد طريقة لمنحه قيمة لتمريرها.

أعتقد أن القيام بذلك يتعارض مع فلسفة IoC إلى حد ما، ولهذا السبب لا يقدمون هذه التسهيلات.يجب أن تكون الحاوية، من الناحية النظرية، قادرة على إعطائك رسمًا بيانيًا كاملاً للكائن في أي ظرف من الظروف، لذلك يجب ألا تضطر أبدًا إلى تمرير المعلمات، وجعل كائناتك تعتمد على معلمات منشئة بخلاف تبعيات الكائنات القابلة للحقن (والتي ستحلها الحاوية بالنسبة لك) يعتبر تصميمًا سيئًا.

لا أستطيع التحدث نيابة عن Windsor أو StructureMap أو الآخرين، مما قد يسمح لك بالقيام بذلك.لا أستطيع حتى أن أقول بشكل قاطع أن Unity ليس لديها طريقة للقيام بذلك لأنني جديد إلى حد ما في ذلك، لكن IIRC Chris Tavares - الذي قام ببناء Unity بشكل أساسي - يتسكع هنا من وقت لآخر، لذلك ربما سيزورنا أجب على هذا :-)

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