2012-06-01 3 views
8

MVC3 웹 사이트에서 Ninject를 사용하여 내 종속성을 해결하려고합니다.ASP.NET MVC3 모델 바인더에서 종속성 삽입 사용

public class UserModelBinder : IModelBinder 
{ 
    //[Inject] 
    public UserDataService userData { get; set; } 

    public object BindModel(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext) 
    { 
     Guid UserID = 
      (Guid)Membership.GetUser().ProviderUserKey; 

     //userDataService = DependencyResolver.Current 
     // .GetService<UserDataService>(); 

     User user = userDataService.GetUser(UserID); 

     return user; 
    } 
} 

코드의 주석 라인을 발견 : 나는 다음과 같은 시나리오를 가지고?

나는 그래서 정말 건설을 통해 주입 할 수 없습니다

ModelBinders.Binders[typeof(User)] = new UserModelBinder(); 

Global.asax 바인더를 등록 할.

UserDataService은 종속 관계 체인 UserDataService -> UserRepository -> Context을가집니다. 그래서 여기서 Ninject를 사용하는 것이 좋을 것입니다.

위의 위의 코드를 userData 선언에서 제거하고 Ninject가 매개 변수로 객체를 삽입하도록 시도하면 문제가 발생합니다. 어떤 이유로 작동하지 않습니다. 널 참조 예외가 발생합니다.

( 그것은 UserDataService가 인터페이스가없는 나는 그 자체로 객체 결합하고있어 일 수 있었다 : kernel.Bind<UserDataService>().ToSelf(); ??)

을 나는 코드의 또 다른 주석 라인이 있습니다

userDataService = DependencyResolver.Current 
    .GetService<UserDataService>(); 

이것이 주석 처리되지 않았을 때 설정이 제대로 작동하지만 올바른 객체가 삽입되었지만 DependencyResolver에 의존하고 있다고 말하면서도 이상한 것은 아닙니다. userDataService = new UserDataService()

내가 놓친 게 있니? 개체를 매개 변수로 주입하고 Ninject 또는 DependencyResolver에 종속성을 도입하지 않는 다른 방법이 있습니까?

+12

감염이라고합니까? – JConstantine

+5

@JLevett : 그 의존성을 주입하는 방법에 따라 감염 될 수 있습니다 .-) –

+1

+1 "좋은 웃음 오타": –

답변

6

모델 바인더는 데이터 변환 만하면되며 서비스에 의존해서는 안되며 확실히 데이터베이스 통신을 트리거하지 않아야합니다. 그것은 귀하의 신청서의 다른 부분에서 이루어져야합니다. 작업 방법은 Guid userId이어야하며 컨트롤러 (또는 하위 레이어, 예 : business command)에서 userDataService.GetUser(UserID);으로 전화해야합니다. 이렇게하면 문제가 존재하지 않습니다.

+1

그래, 처음에는 그랬지만, 그때 나는 userData를 가졌어. 모든 호출에서 .GetUser (UserID)를 컨트롤러 전체에. 또한 컨트롤러에는 두 개의 Guid 객체 (Delete (Guid ID, Guid UserID))가 전달되었고 객체 ID 대신 컨트롤러에 두 개의 UserID가 전달되었습니다. 이 문제를 해결할 방법이 없다면 ... – trailmax

+0

@ trailmax : 라우팅에 문제가있을 수 있습니다. 그리고 그렇지 않다면 여기에서 새로운 질문을 만드십시오. Nontheless, 당신은 잘못된 방식으로이 문제를 해결하고 있습니다. – Steven

+0

네, 요점이 있습니다. 아마 당신의 길을 갈 것입니다. 감사! – trailmax

1

서비스를 받으려면 DependencyResolver.Current을 사용하십시오. 실제로 을 사용하는 것보다 new을 사용하는 것보다 낫습니다. 서비스 유형에 해당 서비스를 결합하지 않았기 때문입니다. 나중에 UserDataService을 추상화하고 클라이언트 코드를 변경하지 않고 다른 변형을 삽입 할 수 있습니다. 이는 실제로 요점입니다.

또한 IDependencyResolver입니다. 따라서이 프레임 워크가 마음에 들면 Ninject를 사용하여 인터페이스를 직접 구현할 수 있습니다.

MVC3에서 의존성 주입을하는 또 다른 방법은 자신 만의 IControllerActivator을 설정하는 것입니다. 원하는 경우 생성자 주입을 대신 수행 할 수 있습니다.

+0

그래, 나는 DependencyResolver가하는 일과 왜 "new"를 통해 만드는 것보다 나은지 이해한다. 어떤 수업이 DI 진행에 대해 전혀 모르고 있습니까? 그러므로 제목 "감염". – trailmax

+2

대부분의 수업은 DI 프레임 워크를 모르는 것입니까? 물론, 거의 모든 사람들이 그것을 모르고 있어야합니다! 캡슐화해야합니다. 주제에 대한 Bob 삼촌의 위대한 기사를 참조하십시오. http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion – tallseth

4

이 작업을 수행 할 수 있습니다 :

public class UserModelBinder : IModelBinder 
{ 
    public Func<UserDataService> UserData { get; set; } 

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     Guid UserID = (Guid)Membership.GetUser().ProviderUserKey; 

     User u = UserData().GetUser(UserID); 

     return u; 
    } 
} 

을 그리고 당신이 그것을 묶을 때

ModelBinders.Binders[typeof(User)] = new UserModelBinder() 
{ 
    userData =() => DependencyResolver.Current.GetService<UserDataService>(); 
} 

이점은 여전히하면서 당신의 UserModelBinder가, 용기가 사용되고 있음을 인식되지 않는 것입니다 주입을 위해 열린다.

그러나 나는 Steven에 동의합니다.이 모델 바인더를 사용하는 것이 옳은 것처럼 보입니다. 대신 컨트롤러에 ICurrentUserContext을 삽입하면 구현시 현재 사용자가 반환됩니다. 그런 다음 컨트롤러 동작에 매개 변수를 추가 할 필요조차 없습니다.

관련 문제