2011-10-28 2 views
4

Ninject.MVC3 확장을 사용하여 MVC 응용 프로그램에서 DI를 설정하는 ASP.NET MVC 3 응용 프로그램이 있습니다. 즉, 내 바인딩이 정의 된 폴더에 NinjectMVC3.cs 파일이 있습니다. 이것은 DI가 내 응용 프로그램의 컨트롤러로 잘 작동합니다.ASP.NET MVC 3 응용 프로그램의 클래스 라이브러리에서 Ninject 참조

ASP.NET MVC 웹 응용 프로그램 외에도 내 솔루션에는 클래스 라이브러리 프로젝트가 포함되어 있습니다. 내 도메인 모델, 서비스 등을 포함하는 MyProject.Core이라고합시다. 거기에서 나는, EmailServices라는 서비스를 사용하므로 같은 UserServices라는 클래스가 : 당신이 볼 수 있듯이, UserServices 클래스 EmailServices에 하드 코딩 된 종속성이

public class UserServices : IUserServices 
{   
    private readonly IEmailServices _emailServices = new EmailServices(); 

    public void CreateUser(...) 
    { 
     // Create user... 

     _emailServices.SendWelcomeEmail(newUser); 
    } 
} 

을,하지만 난에 그것을 위해 싶습니다 DI를 사용하도록 구성 할 수도 있습니다. 즉, 내 ASP.NET MVC 응용 프로그램 (또는 단위 테스트 프로젝트 또는 어느 곳에서든지) "IEmailServices을 사용하여 바인딩 TestEmailServices"이라고 말하고 UserServices 클래스에 TestEmailServices 대신 EmailServices을 사용하고 싶습니다.

어떻게해야합니까? 내가 좋아하는 뭔가를 할 수 있도록하고 싶습니다 :

public class UserServices : IUserServices 
{   
    private readonly IEmailServices _emailServices = kernel.Get<EmailServices>(); 

    ... 
} 

하지만 kernel이 경우에서 와서 어디로 가는지 모르겠어요. 내가 무슨 말을하는거야, 아니면 내가 틀린 나무를 여기에서 짖고 있니?

감사

답변

4

당신은 다음과 같이 생성자 주입이 작업을 수행 할 수 있어야한다 :

당신의 컨트롤러에 서비스 주사 구성된 IoC 컨테이너를 사용 which'll Ninject에 사용자 정의 컨트롤러 공장, 자동으로 처리해야
private readonly IEmailServices _emailServices; 

public UserServices(IEmailServices emailServices) 
{ 
    _emailServices = emailServices; 
} 

당신이 단위 테스트가되면

public class MyController : Controller 
{ 
    private readonly IUserServices _userServices; 

    public MyController(IUserServices userServices) 
    { 
     _userServices = userServices; 
    } 
} 

, 당신은 수동으로 주입 할 수 차례로 컨테이너에 의해 IEmailServices 객체가 주어집니다 컨트롤러가 생성 된 IUserServices 객체를 해결하기 위해 가짜 또는 가짜 전자 메일 서비스를 사용자 서비스에 추가합니다.

+1

예, 대답입니다. Ninject 커널을 서비스 위치 지정자로 사용하지 마십시오. 라이브러리 구현을 Ninject에 연결하지 마십시오. 메인 애플리케이션에서 전체 객체 트리를 구성하게하십시오. – Aaronaught

+0

아, 그냥 그걸 시도 했어야 했어! <이마를 때린다 /> :-) 감사합니다. –

0

어쨌든 MVC 3를 사용하는 경우, 어떻게 함께 Ninject에 등록에 대한 내장 DependencyResolver? 당신이 그것을 필요로하는 곳에

System.Web.Mvc.DependencyResolver.SetResolver(yourKernel); 

그런 다음, 당신은 단지

var svc = System.Web.Mvc.DependencyResolver.Current.GetService<bla>(); 

를 사용할 수 있습니다. SetResolver가 Ninject Kernel을 직접적으로 받아들이거나 래퍼 클래스가 필요한 경우에는 손을 모른다.하지만 가장 깨끗한 해결책이라고 생각한다.

+0

이 작업은 가능하지만 여전히 서비스 로케이터 방지 패턴에 의존하며 MVC에서는 Ninject를 컨트롤러 팩토리로 등록하고 다른 곳에서는 일반 생성자 삽입을 사용할 수 있습니다. 말할 필요도없이 클래스 라이브러리를'System.Web.Mvc'에 연결합니다. 이것은 올바르게 보이지 않습니다. – Aaronaught

+0

@Aaronaught 예, 아니오. MVC 3의 DependencyResolver는 모든 것을 처리합니다 (더 이상 컨트롤러 팩토리가 필요 없기 때문에 DependencyResolver가 해결할 수 있으면 DI를 자동으로 사용함). 그러나 모든 의존성을 주입하는 옵션이 아닌 상황이있을 수 있습니다 (예 :, 일부 형식화 작업을 처리하는 서비스를 사용하는 HtmlHelper가 있습니다.이 작업은 컨트롤러에서 수행하고 모델을 적용 할 수 있지만 표시 기능 만위한 서비스의 경우 과도합니다. –

+0

'DependencyResolver '는 문자 그대로 서비스 위치 지정자입니다. 새로운 이름으로. 나는 커널 자체에서 사용하는 것의 이점을 실제로 볼 수 없다. 그것은 간접적 인 또 다른 계층 일 뿐이다. MVC 내부에있는 것 이상의 합법적 인 필요성이 있다고 확신하지는 않지만, 거기에 모호한 예제가있을 수 있습니다. – Aaronaught

관련 문제