سؤال

شيء ما كان يزعجني منذ أن قرأت إجابة على سؤال آخر stackoverflow (الدقيق يبرزني الآن) حيث ذكر المستخدم شيئًا مثل "إذا كنت تتصل بمركز الخدمة ، فأنت تفعل ذلك بشكل خاطئ."

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

ومع ذلك ، هناك الكثير من الأماكن التي كنت أستخدم فيها محدد موقع الخدمة لحل التبعيات في مشروعي. بمجرد أن يأتي مثال رئيسي من تطبيقات طرازات ModelBinder الخاصة بي.

مثال على الموثق النموذجي النموذجي.

public class FileModelBinder : IModelBinder {
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext) {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");

        IDataContext db = Services.Current.GetService<IDataContext>();
        return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
    }
}

ليس تطبيقًا حقيقيًا - مجرد مثال سريع

نظرًا لأن تنفيذ ModelBinder يتطلب مثيلًا جديدًا عندما يكون الموثق أول المطلوب ، من المستحيل استخدام حقن التبعية على مُنشئ هذا التنفيذ بالذات.

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

كانت هناك مشكلة أخرى قمت بها مؤخرًا (أنني نشرت سؤالاً حولها هنا) هي أن جميع وحدات التحكم الخاصة بي تتطلب مثيلًا من idatacontext الذي استخدمته DI لـ - ولكن واحد تتطلب طريقة الإجراء مثيلًا مختلفًا من idatacontext. لحسن الحظ جاء Ninject لإنقاذ مع التبعية المسماة. ومع ذلك ، شعر هذا وكأنه kludge وليس حل حقيقي.

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

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

  1. متى غير مقبول؟
  2. ما نوع النمط الذي يجب أن أكون عليه في البحث عن الوقت الذي يجب أن أعيد فيه التفكير في كيفية استخدام نمط تحديد موقع الخدمة؟
  3. هل تنفيذ ModelBinder خاطئ؟ إذا كان الأمر كذلك ، فما الذي أحتاجه لتعلم إصلاحه؟
  4. في سؤال آخر على غرار هذا المستخدم مارك سيمان أوصى مصنع مجردة - كيف يرتبط هذا؟

أعتقد أن هذا كل شيء - لا يمكنني التفكير حقًا في أي سؤال آخر للمساعدة في فهمي ولكن أي معلومات إضافية موضع تقدير كبير.

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

أنا لا أبحث عن رمز لإصلاح تطبيق المثال الخاص بي - أتطلع إلى التعلم ، أبحث عن شرح لإصلاح فهمي المعيب.

أتمنى أن يكون لدى Stackoverflow.com القدرة على حفظ مسودة الأسئلة. آمل أيضًا أن يحصل أي شخص يجيب على هذا السؤال من السمعة المناسبة للإجابة على هذا السؤال لأنني أعتقد أنني أطلب الكثير. شكرا لك مقدما.

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

المحلول

النظر في ما يلي:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
  {
    // Foo

    _myInterface = myInterface;
    _myOtherInterface = myOtherInterface;
  }
}

مع هذا التصميم ، يمكنني التعبير عن متطلبات التبعية لنوعي. النوع نفسه ليس مسؤولاً عن معرفة كيفية إنشاء أي من التبعيات ، يتم إعطاؤه (يتم حقنه) بواسطة أي آلية حل يتم استخدامها [عادة حاوية IOC]. بينما:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass()
  {
    // Bar

    _myInterface = ServiceLocator.Resolve<IMyInterface>();
    _myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
  }
}

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

يعتمد الاختيار بين أحدهما أو الآخر حقًا على ما يقدمه المبنى الخاص بك والخدمات التي يقدمها. عادةً إذا كنت تقوم ببناء تطبيق من نقطة الصفر ، فسوف أختار DI طوال الوقت. إنه يحسن القدرة على الصيانة ، ويعزز النموذج ويجعل أنواع الاختبار أسهل كثيرًا. ولكن ، مع أخذ ASP.NET MVC3 كمثال ، يمكنك بسهولة تنفيذ SL كخبز في التصميم.

يمكنك دائمًا الذهاب لتصميم مركب حيث يمكنك استخدام IOC/DI مع SL ، مثل استخدام إلى حد كبير محدد موقع الخدمات المشتركة. يمكن توصيل أجزاء المكون من خلال DI ، ولكن تعرض من خلال SL. يمكنك حتى رمي التكوين في المزيج واستخدام شيء مثل إطار التوسيع المدارة (والذي يدعم نفسه في حد ذاته ، ولكن يمكن أيضًا أن يكون سلكيًا إلى حاويات IOC الأخرى أو محددات الخدمة). إنه خيار تصميم كبير ، عمومًا ، ستكون توصيتي لـ IOC/DI حيثما أمكن ذلك.

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

مع نمط المصنع التجريدي ، يكون المصنع متخصصًا في إنشاء أنواع محددة. لا تقوم بتسجيل أنواع الدقة ، فأنت تسجل مصنعًا مجردًا بشكل أساسي وتبني أي أنواع قد تحتاجها. مع تحديد موقع الخدمة ، تم تصميمه تحديد موقع الخدمات وإعادة تلك الحالات. مماثلة من وجهة نظر الاتفاقية ، ولكن مختلفة جدا في السلوك.

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