2

우리는 StructureMap을 실험 해본 결과 단일 인터페이스에 여러 구현이있는 상황을 처리하는 방법을 파악하는 데 어려움을 겪고 있습니다. 아래 코드는 단일 서비스에서 두 개의 데이터베이스에 액세스 할 수있는 예제를 보여줍니다. 우리는 하나의 컨텍스트 (데이터베이스)했을 때동일한 인터페이스 (StructureMap 또는 다른 DI 프레임 워크)를 사용하는 여러 데이터베이스가있는 IOC

public class SomeController : Controller 
{ 
    private ISomeService _service; 
    private IClientRepository _repository; 
    protected IContext _masterContext; 
    protected IContext _clientContext; 

    public SomeController(ISomeService service, ISomeRepository repository 
     , IContext masterCon, IContext clientCon) 
    { 
     _service = service; 
     _repository = repository; 
     _masterContext = masterCon; 
     _clientContext = clientCon; 
    } 
} 

public class SomeService : ISomeService 
{ 
    private IContext _masterContext; 
    private IContext _clientContext; 

    public SomeService(IContext masterContext, IContext clientContext) 
    { 
     masterContext = _masterContext; 
     clientContext = _clientContext; 
    } 
} 

public class ClientRepository : IClientRepository 
{ 
    private IContext _clientContext; 

    public ClientRepository(IContext clientContext) 
    { 
     _clientContext = clientContext; 
    } 
} 

public class MasterContext : IContext 
{ 
    public MasterContext(String connString) 
    //<snip, snip> implement 3rd party data context 
} 

public class ClientContext : IContext 
{ 
    public ClientContext(String connString) 
    //<snip, snip> implement 3rd party data context 
} 

StructureMap은 훌륭한 일을,하지만 난 방법 2를 해결하는 방법을 어떻게 알 수 있습니까? 참고 : 대부분의 상황에서는 2 개의 데이터베이스를 처리하는 서비스가 없지만 2 개의 데이터베이스를 액세스하는 2 개의 저장소가있는 2 개의 연결을 처리하는 컨트롤러가있을 수 있습니다.

저는 IOC 프레임 워크를 포기하고 가난한 사람의 DI로 돌아갈 준비가되어 있습니다.

+0

나는 비슷한 상황에 처해있다. 그래서 저는 이미 3 개의 다른 repos가 제 컨트롤러에 주입되어 있고 저는 4 번째를 추가하려고합니다. 그리고 여러분을 좋아합니다 -이 문제에 대한 해결책이 있어야한다고 생각합니다. 아이러니 한 것은 모두 기본 : Add, Update, FindSingle, FindMany, Delete 및 SaveChanges 메소드가 다른 Context를 요구한다는 점입니다. 누구든지 예제가있어? – ozzy432836

답변

2

IClientContextIMasterContext은 가능한 경우 IContext을 상속받을 수 있습니까? 제 생각에이 코드는 '마스터'또는 '클라이언트'데이터베이스 중 어느 것을 사용 하느냐에 따라 크게 다른 두 가지 작업 중 하나입니다.

1

Unity에서 이름 지정 등록을 할 수 있으므로 주어진 인터페이스에 대해 클래스 이상을 효과적으로 등록 할 수 있습니다. 그래서 당신은 (마음으로 입력을하면 관심 실제 유니티 문서 확인) 할 수있는 :

container.RegisterType<IContext, MasterContext>("Master"); 
container.RegisterType<IContext, ClientContext>("Client"); 

을 다음 SomeService의 생성자는 다음과 같습니다

public SomeService(
    [Dependency("Master")]IContext masterContext, 
    [Dependency("Client")]IContext clientContext) 
{ 
    //... 
} 

을 단점은이이 방법으로 서비스에 클래스는 더 이상 사용 된 DI 프레임 워크와 독립적이지 않지만 프로젝트에 따라 다를 수 있습니다.

1

StructureMap을 사용하여 종속성을 자동으로 해결하는 경우 약간 어려울 수 있습니다. 첫 번째 솔루션 (그리고 내가 잘못 생각한 부분)은 Richard의 답변과 같은 마커 인터페이스를 사용하여 등록하는 것입니다. 그런 다음 클라이언트 또는 마스터 컨텍스트를 명시 적으로 지정할 수 있습니다.

두 번째 방법은 명명 된 등록을 사용하고 명시 적으로 생성자 params를 지정하는 것입니다.

ForRequestedType<IContext>().AddInstances(
    i => { 
     i.OfConcreteType<ClientContext>().WithName("Client"); 
     i.OfConcreteType<MasterContext>().WithName("Master"); 
    }); 
ForRequestedType<SomeController>().TheDefault.Is.ConstructedBy(
    i => new SomeController(i.GetInstance<ISomeService>(), 
     i.GetInstance<IClientRepository>(), 
     i.GetInstance<IContext>("Master"), 
     i.GetInstance<IContext>("Client"))); 

특히 좋지는 않지만 일을 처리하고 궁극적으로 그것이 한두 곳 밖에 없다면 괜찮을 수도 있습니다. 당신이 다른 네임 스페이스/어셈블리 해결하려면


이 같은 것을 시도해 볼 수도 있습니다 : - ParentType에 술어가 (당신이 정말로 원하는 나) 총회에 참조 할 수

ForRequestedType<IContext>().AddInstances(
    i => { 
     i.OfConcreteType<ClientContext>().WithName("Client"); 
     i.OfConcreteType<MasterContext>().WithName("Master"); 
    }).TheDefault.Is.Conditional(c => { 
     c.If(con => con.ParentType.Namespace.EndsWith("Client")) 
      .ThenIt.Is.TheInstanceNamed("Client"); 
     c.If(con => con.ParentType.Namespace.EndsWith("Master")) 
      .ThenIt.Is.TheInstanceNamed("Master"); 
     c.TheDefault.Is.OfConcreteType<ClientContext>(); 
    }); 

+0

우리는 실제로 모든 곳 (수십 개의 컨트롤러)에서 이것을 사용합니다.하위 레벨에서는 프로젝트별로 컨텍스트가 하나만 사용되도록 분리 할 수 ​​있습니다 (클라이언트와 마스터 프로젝트가 따로 따로 있습니다). 그러나 프로젝트/어셈블리별로 다르게 해결하도록 StructureMap을 설정하는 방법을 알지 못했습니다. –

+0

다르게 해결하는 방법에 대한 업데이트 총회 –

관련 문제