1

데이터를 별도의 인터페이스로 읽지 못하게하는 CQRS를 구현하는 MVC 애플리케이션이 있습니다. 이러한 인터페이스의 구체적인 인스턴스를 컨트롤러에 주입하기 위해 생성자 주입을 사용하고 있습니다. 생성자 삽입의 경우 Unity 컨테이너를 사용하고 있습니다. 아래 예제를 참조하십시오.MVC : 조건부로 오버로드 된 생성자 호출

//The Employee controller 
public class EmployeeController : Controller 
{ 
    IEmployeeRepository _Writer; 

    IEmployeeQuery _Reader; 

    //constructor injection 
    public EmployeeController(IEmployeeRepository writer, IEmployeeQuery reader) 
    { 
     this._Writer = writer; 
    this._Reader = reader; 

    } 


    //To Do: constructor injection for write operations only 
    public EmployeeController(IEmployeeRepository writer) 
    { 
     this._Writer = writer; 

    } 

    //To Do: constructor injection for read operations only 
    public EmployeeController(IEmployeeQuery reader) 
    { 
     this._Reader = reader; 

    } 
} 


//Registration of the concrete types in the unity container. 
public static class Bootstrapper 
{ 
    public static void ConfigureUnityContainer() 
    { 
     IUnityContainer container = new UnityContainer(); 

     container.RegisterType<IEmployeeRepository, EmployeeRepository>(new HttpContextLifetimeManager<IEmployeeRepository>()); 
     container.RegisterType<IEmployeeQuery, EmployeeQueries>(new HttpContextLifetimeManager<IEmployeeQuery>()); 
     ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 
    } 
} 

//The derived Controller Factory for injection dependencies in the Controller constructor 
public class UnityControllerFactory : DefaultControllerFactory 
{ 
    IUnityContainer container; 

    public UnityControllerFactory(IUnityContainer container) 
    { 
     this.container = container; 
    } 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 


     try 
     { 
      if (controllerType == null) 
      { 
       throw new ArgumentNullException("controllerType"); 
      } 

      if (!typeof(IController).IsAssignableFrom(controllerType)) 
      { 
       throw new ArgumentException(String.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType"); 
      } 

      return container.Resolve(controllerType) as IController; 





     } 
     catch (Exception) 
     { 

      return null; 
     } 
    } 
} 

나는 모든 작업에 대해 데이터를 가져 오거나 데이터를 쓰지만 둘 다를 쓰지는 않을 것이라고 생각했습니다. 이 경우 초기화 할 필요가있는 "_Writer"또는 "_Reader"중 어떤 것을 조건으로 컨트롤러 생성자를 조건부로 호출해야합니다.

어떻게이 작업을 수행 할 수 있습니까?

답변

1

컨트롤러를 두 개 사용해야하는 것처럼 보입니까? 읽고 쓸 수 있어야 할 필요가 전혀 없으면 그 구성 요소를 단일 책임으로 리팩토링하는 것을 고려할 것입니다.

만약 당신이 그것을하고 싶지 않다면, 나는 그 의존성을 주입하지 않고 NullObject를 주입하는 것을 고려할 것입니다. this thread을 참조하십시오.

TecX project에는 NInject의 컨텍스트 바인딩을 모방하는 확장이 포함되어 있습니다. 그렇게하면 어떤 종속성을 주입 할지를 지정할 수 있습니다. 코드는 TecX.Unity 프로젝트 (폴더 ContextualBinding) 안에 있습니다. 사용 방법을 보여주는 테스트는 TecX.Unity.ContextualBinding.Test 프로젝트 내에 있습니다.

+0

@@ 세바스찬, 내가 본되지 않은 여러 컨트롤러, 이론적으로 가능 보이지만. 이것이 어떻게 달성 될 수 있는지에 대한 예를 보여줄 수 있습니까? 다른 옵션을 시도하기 전에 개념적으로 올바른 단일 책임 옵션을 선호합니다. – devanalyst

+0

@devanalyst MVC에 대한 전문가가 아닙니다. 이 가이드 라인은 어떤 종류의 아키텍처에서도 유용하다고 생각합니다. 독립적으로 작동하는 두 개의 개별 파트가있는 경우 - 동일한 클래스에 넣지 않으려면 SRP를 위반합니다 (일반적으로). 읽기 또는 쓰기 만 할 때와 실제로 같은 시각입니까? 그렇다면 동일한보기에 의해 트리거 된 두 가지 (읽기 및 쓰기)를 모두 수행 할 수 있습니다. 실제로 수행해야 할 작업이 있습니까? 리더 또는 작가 만 투입하는 것이 가치가 있습니까? 그냥 몇 가지 아이디어. –

+0

@devanalyst 맞습니다! 일반적으로 동일한보기에 대해 여러 컨트롤러가있는 것은 맞지 않습니다. 대신 다양한 CRUD 작업에 대해 동일한 컨트롤러 클래스에 여러 메서드 (MVC 패러다임의 작업)가 있습니다. 종속성은 사용 여부에 관계없이 매번 주입해야합니다. 또한 DI 컨테이너를 구성 할 때 특정 인터페이스를 구현하는 클래스의 이름을 알 수 있습니다. 오버로드 된 생성자가 여러 개있는 경우 구현의 인스턴스를 만들기 위해 특정 생성자를 호출하도록 구성 할 수 없습니다. – RBT

관련 문제