2011-09-05 8 views
1

EF 코드 (4.1)를 사용하여 데이터베이스와 통신하기 위해 CustomerService를 사용하는 커스텀 멤버십이 있습니다. ninject를 사용하여 CustomerService를 커스텀 멤버십 클래스에 삽입합니다. 하지만 유효성을 검사하려고 할 때 컨텍스트에 오류가 발생합니다. 내 문맥에서 저장소와 서비스가 InRequestScope()이기 때문입니다. 그리고 [맞춤]을 사용하여 CustomerService를 내 맞춤 멤버십의 속성에 삽입하고 ninject에서 _kernel.Inject (Membership.Provider)를 사용하기 때문에 시작시에만 주입됩니다.MVC 3 커스텀 멤버쉽 컨텍스트 삭제 오류

이 문제에 대한 많은 게시물을 읽었지만이 문제를 해결하는 대답을 찾을 수 없습니다.

누구에게도 해결책이 있습니까?

답변

9

DI 및 IoC 컨테이너로 시작하는 사람들에게 흔히있는 실수입니다. 범위의 일관성을 유지해야합니다. 은 의존성이있는 서비스가 싱글 톤 범위에 바인딩 될 때 요청 범위에 종속 된 종속성을 가질 수 없습니다 (또는 더 나쁜 것은 컨테이너가 전혀 관리하지 않는 일부 범위를 가짐). 그것은 단순히 잘못된 것입니다.

당신은 여기에 두 가지 기본 옵션이 있습니다

  1. 바인드 멤버 자격 공급자 자체와 함께 InSingletonScopeCustomerService을. 분명히 이것은 장수명의 EF 서비스의 모든 일반적인 단점을 가지고 있습니다.

  2. 회원 공급자가 CustomerService 인스턴스에 의존하지 않도록하십시오. 대신 을 만들 수있는 CustomerServiceFactory에 종속성을 만들고CustomerService 인스턴스를 만들고 구성원 공급자에 대한 모든 호출을 일시적으로 처리하십시오. # 2의

는 만들고 공장을 결합하는 과정은 매우 간단합니다 : 당신의 모듈에 다음

public interface ICustomerServiceFactory 
{ 
    ICustomerService GetService(); 
} 

public class NinjectCustomerServiceFactory : ICustomerServiceFactory 
{ 
    private readonly IKernel kernel; 

    public NinjectCustomerServiceFactory(IKernel kernel) 
    { 
     if (kernel == null) 
      throw new ArgumentNullException("kernel"); 
     this.kernel = kernel; 
    } 

    public ICustomerService GetService() 
    { 
     return kernel.Get<ICustomerService>(); 
    } 
} 

:

Bind<ICustomerService>() 
    .To<EFCustomerService>(); 
    .InRequestScope(); 
Bind<ICustomerServiceFactory>() 
    .To<NinjectCustomerServiceFactory>() 
    .InSingletonScope(); 

참고 범위 여기. 서비스 자체는 여전히 요청 범위이지만 팩토리는 공급자와 동일한 범위 인 싱글 톤입니다. 이것은 팩토리가 싱글 톤 (더 많거나 적음) 인 커널에 직접 연결되기 때문에 가능합니다.

당신은 너무처럼 보이는 회원 코드로 끝날 것 :

public class MyMembershipProvider : MembershipProvider 
{ 
    public override MembershipUserCollection GetAllUsers() 
    { 
     var service = serviceFactory.GetService(); 
     var serviceUsers = service.GetAllUsers(); 
     return serviceUsers.Select(u => CreateMembershipUser(u)); 
    } 

    // Other methods... 

    [Inject] 
    public ICustomerServiceFactory ServiceFactory { get; set; } 
} 
서비스 자체는 여전히 요청 범위의 것이기 때문에 이것은 실제로 매우 잘 작동

하지만 공장 (및 멤버 자격 공급자)를합니다 각 요청 중에 다른 인스턴스를 가져와야합니다. 뿐만 아니라 멤버쉽 공급자는 단일 요청 중에 얼마나 많은 멤버십 메소드가 호출되는지에 관계없이 과 동일한 인스턴스 (공장을 통해)를 얻을 수 있습니다. 따라서 레거시 코드에 통합해야 함에도 불구하고 DI의 거의 모든 이점을 얻게됩니다.

+0

느낌이 바보 같아서, ninject가 Memebership 공급자에게 속성을 주입하지 않는 문제를 탐색하는 동안 질문을 읽지도 않았고, 다른 문제의이 솔루션을 구현했습니다. 물론, 아직 주입되지 않았습니다. 재산. 그리고 멤버쉽 제공 업체에서 생성자의 상처를 사용할 수 없습니다 ... –

관련 문제