3

내 응용 프로그램은 하나 이상의 "플러그인"어셈블리를 동적으로로드 할 수있는 모듈 식 아키텍처를 구현합니다. 각 어셈블리에는 IPlugin 인터페이스를 구현하는 클래스가 포함되어 있으며 호스트 응용 프로그램이 플러그인과 상호 작용할 때 사용하는 다양한 메서드와 속성을 제공합니다.클래스 의존성/리팩토링을 어떻게 관리해야합니까?

이 클래스는 필연적으로 플러그인 내의 다른 클래스에 종속되므로 필연적으로 고유 한 종속성을 가질 수 있습니다. 지금까지 Castle Windsor (각 플러그인에는 종속성을 등록하는 IWindsorInstaller이 포함되어 있음)를 사용하여이 모든 것을 관리하고 생성자를 통해 DI를 수행했습니다. 단점은이 접근 방식이 작동하려면 클래스가 public이어야한다는 것입니다.

나는 지금 내 감각에 와서 모든 클래스를 만들어서 플러그인을 잠그고 싶지만 internal,하지만 아마도 최선의 방법으로 종속성을 처리 할 수 ​​있을지는 잘 모르겠다. 윈저를 사용하십시오. 클래스가 자신의 종속성 (느슨하게 결합되지 않았거나 테스트 가능성이 없음)을 인스턴스화하는 것을 원하지 않으므로 다른 접근 방식이 있습니까?

답변

3

단점은이 접근 방식을 적용하려면 클래스가 공개되어야한다는 것입니다. .

이것은 사실이 아닙니다. 내부에있는 것들을 등록 할 수는 있지만 Castle Windsor (또는 DI 컨테이너)의 자동 배선 (자동 생성자 주입) 기능이 느슨 할 것입니다. 이러한 유형을 수동으로 만드는 대리인을 등록하여 내부 항목을 등록 할 수 있습니다. 예를 들어 : 자동 배선 조립에 플러그 가장 유지 보수의 구성 루트를 유지,하지만 난 상황에서 좋은 대안이 있다고 생각하지 않기 때문에

container.Register(Component.For<IService>() 
    .UsingFactoryMethod(() => 
    { 
     var log = container.Resolve<ILogger>(); 
     return new RealService(log); 
    }) 
    .LifeStyle.Transient); 

수동 new과 서비스를 개발하는 것은 차선책이다. 그래도 각 서비스가 자체 의존성 (가난한 사람의 DI)을 만드는 것보다 낫습니다.

UPDATE

내가 뭔가를 기억 :

container.Register(Component.For<IService>() 
    .ImplementedBy<RealService()); 
: 당신은 이것과 같은 일반적인 방법을 사용하여 그 내부 유형을 등록 할 때 여전히 내부 종류의 자동 배선을 할 수 있어야한다

이 작업을 수행하려면 RealService의 생성자를 공개로 설정해야합니다 (단, RealService 자체는 내부 일 수 있음). 이것은 매우 제한적인 Silverlight 샌드 박스에서 실행될 때 (또는 최소한 Simple Injector와 작동하지만 Castle이이를 수행 할 수 있어야 함)와 같이 부분 신뢰 인 에서도 작동합니다.

+0

응답 해 주셔서 감사합니다. 또한 공개 ctr을 가진 내부 유형을 등록 할 수 있다는 사실을 깨달았습니다. 그것은 또 다른 "디자인"질문을 일으킨다. 나는 현재이 의존성을 내 IPlugin 클래스의 ctr에 주입하고있다. 그러나 클래스는 플러그인에 대한 공개 API로 간주 될 수 있으므로이 ctr 매개 변수가 있으면 잘못된 것입니다.내가 그들을 제거하면 의존성을 해결하는 대안이 무엇이겠습니까? 서비스 위치 지정자를 사용 하시겠습니까? –

+0

플러그인 라이브러리가 여러 가지 방법으로 사용할 수있는 고객에게 제공되는 경우 공개 API에 해당 종속성이있는 생성자가 있지만 회사 내에서 사용하기에 불편할 수 있습니다 (DI 컨테이너를 사용하는 경우).) 이것은 아마도 문제가되지 않습니다. 두 경우 모두 내부에서 해당 유형을 만들고 소비자가 상호 작용할 수있는'PluginFactory' 클래스를 사용할 수 있습니다. 또는 공용 플러그인 클래스와 팩토리를 모두 사용하십시오. – Steven

0

Ninject를 사용하는 경우 바인딩을 구성하는 각 어셈블리에 NinjectModule을 추가 한 다음 호스트 응용 프로그램에서 바인딩을 등록하기 위해 모듈을로드하기 만하면됩니다.

public class ServiceModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IService>().To<RealService>(); 
    } 
} 

RealService은 내부에 머무를 수 있으며 모듈은 동일한 어셈블리 안에 있기 때문에 모듈이 볼 수 있습니다.

+0

이 부분 신뢰도에서 작동합니까? – Steven

+0

좋은 질문입니다, 확실하지 않습니다 ... Ninject 문서가 당신에게 말할 수 있습니다 –

+0

NinjectModule은 본질적으로 이미 사용하고있는 IWindsorInstaller와 같습니다. 위의 스티븐 (Steven)의 대답과 내 부류에 관한 내 의견을 참조하십시오. –

관련 문제