문제

부트 스트랩퍼에서 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>();
    }    
}
도움이 되었습니까?

해결책

나는 당신이 단일 책임 원칙 (SRP)과 공개/폐쇄 원칙 (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 물체. 그런 다음 a를 정의합니다 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는 반사를 사용하여 이러한 클래스를 찾을 수 있으며 스타트 업에서 모든 매퍼를 초기화합니다.

만약 당신이 위반하고있는 단일 책임 원칙이라면, 수업은 여러 가지 이상의 변화가 있다는 것입니다.

나는 개인적으로 Automapper에 대한 모든 구성이 완료된 configureeautomapper 클래스를 가질 것입니다. 그러나 그것은 개인적인 선택에 달려 있다고 주장 할 수있다.

OMU, 나는 앱의 시작 루틴에서 IOC 컨테이너를 부트 스트랩하는 것과 관련하여 비슷한 질문으로 씨름합니다. IOC의 경우, 제가 제공 한 지침은 변경 사항을 추가 할 때 앱 전체에 뿌려지는 대신 구성을 중앙 집중화하는 이점을 지적합니다. Automapper를 구성하기 위해서는 중앙 집중식의 장점이 훨씬 덜 중요하다고 생각합니다. Automapper 컨테이너를 IOC 컨테이너 또는 서비스 로케이터에 넣을 수있는 경우, Luben Bartelink의 어셈블리 또는 정적 생성자 또는 분산 된 내용으로 매핑을 구성하겠다는 Ruben Bartelink의 제안에 동의합니다.

기본적으로, 나는 당신이 부트 스트랩을 중앙 집중화 할 것인지를 결정하는 문제로 본다. 스타트 업 루틴의 개방형/폐쇄 원리에 대해 우려하는 경우, 분산과 함께 가십시오. 그러나 OCP에 대한 준수는 한 곳에서 수행 된 모든 부트 스트랩의 가치를 대가로 전화를 걸 수 있습니다. 또 다른 옵션은 Automapper에 그러한 개념이 있다고 가정 할 때 부트 스트랩퍼가 레지스트리에 대한 특정 어셈블리를 스캔하도록하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top