2011-08-04 6 views
5

나는 이러한 인터페이스를 가지고는도움말

public class SqlUnitOfWork : IUnitOfWork 
{ 
    private readonly DbContext dbContext; 

    public SqlUnitOfWork() 
    { 
     dbContext = new DbContext("name=SQLContainer"); 
    } 

    public IPersonRepository People 
    { 
     get { return IoC.Container.Resolve<IPersonRepository>(new { DbContext = dbContext }); } 
    } 

    public IBookRepository Books 
    { 
     get { return IoC.Container.Resolve<IBookRepository>(new { DbContext = dbContext }); } 
    } 

    public int Commit() 
    { 
     return dbContext.SaveChanges(); 
    } 
} 

IBookRepositoryIPersonRepository의 구현은 소요 생성자를 사용 DbContext을 매개 변수로 사용하며이 DbContext는 SqlUnitOfWork (위의 코드)에서 만들어지고 Resolve 메서드의 오버로드를 사용하여이 매개 변수를 전달합니다.

제 질문은 이것이 올바른 방법입니까? 이것은 좋은 습관입니까?

감사합니다.

+0

[이 기사] (http://bit.ly/bF7jL3)를보십시오. 비슷한 apprach 보여줍니다. 그것은 당신에게 몇 가지 아이디어를 줄 수 있습니다. – Steven

답변

8

DI 컨테이너를 Service Locator can hardly be said to be good practice으로 사용. 이 외에도 인터페이스를 확인하는 동안 DbContext을 컨테이너에 전달하면 누설 추상화이됩니다. 왜냐하면 누락되어서는 안되는 구체적인 구현에 대해 알고 있다는 것을 의미하기 때문입니다.

대신 나는 이런 식으로 뭔가를 갈 것이다, 생성자 삽입를 추천 할 것입니다 : DbContext의 명시 적 공유가 없습니다

public class SqlUnitOfWork : IUnitOfWork 
{ 
    private readonly DbContext dbContext; 
    private readonly IPersonRepository personRepository; 
    private readonly IBookRepository bookRepository; 

    public SqlUnitOfWork(DbContext dbContext, 
     IPersonRepository personRepository, IBookRepository bookRepository) 
    { 
     if (dbContext == null) 
      throw new ArgumentNullException("dbContext"); 
     if (personRepository == null) 
      throw new ArgumentNullException("personRepository"); 
     if (bookRepository = null) 
      throw new ArgumentNullException("bookRepository"); 

     this.dbContext = dbContext; 
     this.personRepository = personRepository; 
     this.bookRepository = bookRepository; 
    } 

    public IPersonRepository People 
    { 
     get { return this.personRepository; } 
    } 

    public IBookRepository Books 
    { 
     get { return this.bookRepository; } 
    } 

    public int Commit() 
    { 
     return this.dbContext.SaveChanges(); 
    } 
} 

에도 불구하고,이 컨테이너를 통해 구성 할 수 있습니다. 이 질문의 컨텍스트에서 Castle Windsor가 사용중인 컨테이너임을 나타내므로 기본 수명은 이미 Singleton이므로 이 명시 적으로 설정되어 있지 않습니다. Castle Windsor를 사용하면 DbContext이 자동으로 SqlUnitOfWork 클래스와 두 저장소간에 공유됩니다. 당신이 API가 다른 것이 또 다른 DI 컨테이너를 사용한다면

container.Register(Component.For<DbContext>().LifeStyle.Singleton); 

하지만 개념은 동일합니다

그러나, 당신은 명시 적으로 다음과 같이 공유 할 컨텍스트를 구성 할 수 있습니다.

보너스 정보 : 나는 전체적인 맥락이 무엇인지 모르겠지만, 경우이 웹 응용 프로그램에서 사용되는 및 DbContext는 SQL 컨텍스트에 엔티티 프레임 워크 또는 LINQ이며, 정확한 수명 구성 대신 할 것 PerWebRequest는 스레드로부터 안전합니다.

container.Register(Component.For<DbContext>().LifeStyle.PerWebRequest); 
+0

은 컨스트럭터 주입에 적합하지 않습니다. 웹 요청은'SqlUnitOfWork.People.Get (322); 만 필요하지만 bookRepository 인스턴스도 필요하지는 않지만 생성됩니다 (생성자에 포함). – Omu

+1

http://blog.ploeh.dk/2011/ 03/04/ComposeObjectGraphsWithConfidence.aspx –