سؤال

وأنا تكوين Automapper في الإطلاق وأسميه Bootstrap() في Application_Start()، ولقد قيل لي أن هذا غير صحيح لأن لدي لتعديل صفي Bootstrapper في كل مرة لا بد لي من إضافة تعيين جديد، لذلك أنا انتهاك مبدأ المفتوح مغلقة.

وكيف ترى، هل أنا حقا انتهاك هذا المبدأ؟

public static class Bootstrapper
{
    public static void BootStrap()
    {
        ModelBinders.Binders.DefaultBinder = new MyModelBinder();
        InputBuilder.BootStrap();
        ConfigureAutoMapper();
    }

    public static void ConfigureAutoMapper()
    {
        Mapper.CreateMap<User, UserDisplay>()
            .ForMember(o => o.UserRolesDescription,
                       opt => opt.ResolveUsing<RoleValueResolver>());
        Mapper.CreateMap<Organisation, OrganisationDisplay>();
        Mapper.CreateMap<Organisation, OrganisationOpenDisplay>();
        Mapper.CreateMap<OrganisationAddress, OrganisationAddressDisplay>();
    }    
}
هل كانت مفيدة؟

المحلول

وأنا أزعم أن أنت تنتهك مبدأين: مبدأ المسؤولية واحدة (الخطة) وفتح / إغلاق مبدأ (OCP)

وأنت تنتهك SRP لأن فئة إلباس الحذاء لها أكثر من سبب واحد لتغيير: إذا قمت بتغيير نموذج ملزم أو التكوين التلقائي مخطط

هل سيكون انتهاك OCP لو كنت لإضافة رمز إلباس الحذاء إضافي لتكوين عنصر فرعي آخر للنظام.

وكيف يمكنني التعامل مع هذا عادة هو أن أحدد واجهة التالية.

public interface IGlobalConfiguration
{
    void Configure();
}

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

public class AutoMapperGlobalConfiguration : IGlobalConfiguration
{
    private readonly IConfiguration configuration;

    public AutoMapperGlobalConfiguration(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public void Configure()
    {
        // Add AutoMapper configuration here.
    }
}

public class ModelBindersGlobalConfiguration : IGlobalConfiguration
{
    private readonly ModelBinderDictionary binders;

    public ModelBindersGlobalConfiguration(ModelBinderDictionary binders)
    {
        this.binders = binders;
    }

    public void Configure()
    {
        // Add model binding configuration here.
    }
}

وأنا استخدم Ninject لحقن التبعيات. IConfiguration هو تنفيذ الكامنة وراء الطبقة AutoMapper الثابتة وModelBinderDictionary هو موضوع ModelBinders.Binder. ثم أود أن تحديد NinjectModule التي من شأنها أن تفحص التجمع محددة لأية فئة التي تطبق الواجهة IGlobalConfiguration وإضافة هذه الفئات إلى مركب.

public class GlobalConfigurationModule : NinjectModule
{
    private readonly Assembly assembly;

    public GlobalConfigurationModule() 
        : this(Assembly.GetExecutingAssembly()) { }

    public GlobalConfigurationModule(Assembly assembly)
    {
        this.assembly = assembly;
    }

    public override void Load()
    {
        GlobalConfigurationComposite composite = 
            new GlobalConfigurationComposite();

        IEnumerable<Type> types = 
            assembly.GetExportedTypes().GetTypeOf<IGlobalConfiguration>()
                .SkipAnyTypeOf<IComposite<IGlobalConfiguration>>();

        foreach (var type in types)
        {
            IGlobalConfiguration configuration = 
                (IGlobalConfiguration)Kernel.Get(type);
            composite.Add(configuration);
        }

        Bind<IGlobalConfiguration>().ToConstant(composite);
    }
}

وأود أن قم بإضافة التعليمة البرمجية التالية إلى ملف Global.asax.

public class MvcApplication : HttpApplication
{
    public void Application_Start()
    {
        IKernel kernel = new StandardKernel(
            new AutoMapperModule(),
            new MvcModule(),
            new GlobalConfigurationModule()
        );

        Kernel.Get<IGlobalConfiguration>().Configure();
    }
}

والآن قانون بلدي إلباس الحذاء تلتزم كل من SRP وOCP. يمكنني بسهولة إضافة كود إلباس الحذاء إضافية من خلال خلق فئة التي تطبق الواجهة IGlobalConfiguration وصفوفي التكوين العمومي ديك سبب واحد فقط للتغيير.

نصائح أخرى

لديك مغلقة تماما، هل يمكن أن يكون مهيئ ثابت في تسجيل رسم الخرائط، ولكن ذلك سيكون مبالغة.

وبعض الأشياء مفيدة فعلا قد مركزية إلى درجة من وجهة نظر من أن تكون قادرة على عكس مهندس بالرغم من ذلك.

في NInject، هناك فكرة وجود Module لكل مشروع أو الفرعي (مجموعة من المشاريع)، والذي يبدو حلا وسطا معقولا.

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

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

وأنا شخصيا لدى فئة ConfigureAutoMapper الذي يتم كل ما عندي من التكوين لAutoMapper مع. ولكن يمكن القول أنه هو وصولا الى اختيار شخصي.

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

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

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