2010-01-13 1 views
58

은 내가 Ninject에 모듈의 여러 인스턴스를 따로 따로 다른 사람의 코드를 당겨 발견했습니다Ninject 모듈의 의도는 무엇입니까? 클래스 Ninject.Modules.Module에서 파생, 그리고 대부분이 포함 된 부하 방법이 -

Ninject에하는 완전한 안돼서 그들의 코드.

이러한 클래스는 StandardKernel 인스턴스의 LoadModule 메서드를 호출하고 모듈 클래스의 인스턴스를 전달하여 호출됩니다.

어쩌면 여기서 명백한 것을 놓치고 있을지 모르겠다.하지만 평범한 구식 클래스를 만들고 그 메서드 또는 정적 메서드를 사용하는 정적 클래스를 호출하는 것 이상의 이점은 무엇일까요?

 

답변

61

Ninject에 모듈 IOC의 용기와 다양한 유형을 등록하는 데 사용되는 도구이다. 장점은 이러한 모듈이 자체 클래스에 보관된다는 것입니다. 이렇게하면 다른 계층/서비스를 자신의 모듈에 넣을 수 있습니다.

// some method early in your app's life cycle 
public Kernel BuildKernel() 
{ 
    var modules = new INinjectModule[] 
    { 
     new LinqToSqlDataContextModule(), // just my L2S binding 
     new WebModule(), 
     new EventRegistrationModule() 
    }; 
    return new StandardKernel(modules); 
} 

// in LinqToSqlDataContextModule.cs 
public class LinqToSqlDataContextModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IRepository>().To<LinqToSqlRepository>(); 
    } 
} 

여러 모듈을 사용하면 IoC 컨테이너에서도 문제를 분리 할 수 ​​있습니다.

질문의 나머지 부분은 Ninject가 아니라 IoC와 DI에 관한 것입니다. 예, 정적 구성 객체를 사용하여 IoC 컨테이너가 수행하는 모든 작업을 수행 할 수 있습니다. IoC 컨테이너는 여러 계층의 종속성이있을 때 매우 유용합니다.

public interface IInterfaceA {} 
public interface IInterfaceB {} 
public interface IInterfaceC {} 

public class ClassA : IInterfaceA {} 

public class ClassB : IInterfaceB 
{ 
    public ClassB(IInterfaceA a){} 
} 

public class ClassC : IInterfaceC 
{ 
    public ClassC(IInterfaceB b){} 
} 

Building ClassC는 인터페이스의 다중 깊이가있는이 시점에서 고통입니다. 커널에 IInterfaceC를 요청하는 것이 훨씬 쉽습니다.

var newc = ApplicationScope.Kernel.Get<IInterfaceC>(); 
+1

LinqToSqlDataContextModule은 StandardModule을 확장해야합니까? –

+1

@Mark Gibaud in Ninject 2. StandardModule이 없어지고 NinjectMdule로 바뀌 었습니다 - http://github.com/enkari/ninject/tree/master/src/Ninject/Modules/ –

+1

그 좋은 예입니다 만, 테스트 가능성은 어떻습니까? 저는 DI/IoC 컨테이너가 테스트 가능성을 어떻게 도울 수 있는지에 대해 끊임없이 들었습니다.하지만 Ninject가 코드를 오염시키지 않고 테스트 가능성을 촉진한다는 것을 보여주는 실제 사례를 찾기가 힘듭니다. 아이디어를 얻기 위해 볼 수있는 실제 공개 소스 프로젝트가 있습니까? –

9

아마 내가 여기 분명 뭔가 누락,하지만 그냥 평범한 구식 클래스 를 생성하고 정적 인 방법과 그 방법, 또는 아마도 정적 클래스를 호출하는 동안이 의 이익을 무엇을하고있어 ?

예, 모듈을 사용하지 않고 바인딩을 설정하려면 Bind<X>().To<Z>() 문장을 호출하면됩니다.

  • IKernel.Load(IEnumerable<Assembly>) 반사를 통해 이러한 모듈을 동적으로 발견하고로드 할 수 있습니다 :

    차이점은 다음 모듈이 문을 넣을 경우이다.

  • 바인딩은 이름 아래에 논리적으로 그룹화됩니다. 당신은
3

IKernel.Unload(string) 어쩌면 내가 여기서 뭔가를 분명 누락으로 다시 언로드이 이름을 사용할 수 있지만, 단지 아마도 평범한 오래된 클래스를 생성하고 메서드를 호출 이상이의 장점은 무엇인가 정적 메서드를 사용하는 정적 클래스?

우리에게있어서, 그것은 나중에 쉽게 테스트를 추가 할 수있는 능력입니다. 그냥 mockobjects 및 voila ..... 몇 바인딩을 재정 의하여레거시 코드에서 "모든 것"을 묶은 DI가 없으면 재 작업없이 테스트 사례를 삽입하는 것이 거의 불가능합니다. DI가 제 위치에 있고 DI가 모든 것을 연결 한 곳에서 올바르게 사용되는 한, 아주 추악한 레거시 코드에서도 매우 간단합니다.

많은 DI 프레임 워크에서 mockobjects로 특정 바인딩을 덮어 쓰는 테스트 모듈로 테스트 용 생산 모듈을 사용할 수 있습니다. 나머지 배선은 그대로 둡니다. 이것들은 단위 테스트보다 시스템 테스트 일지 모르지만 클래스 간의 통합을 테스트 할 때 일반 개발자보다 높은 수준의 테스트를 선호하는 경향이 있습니다. 프로젝트에 참여하고 전체 기능을 실제로 볼 수있는 사람에게는 위대한 문서입니다 (대신 전체 시스템을 설정하지 않아도 됨).