2011-08-04 53 views
5

我有這些接口:幫助溫莎和工作模式庫和單位

public interface IUnitOfWork 
{ 
    IPersonRepository People { get; } 
    IBookRepository Books { get; } 
    int Commit(); 
} 

public interface IBookRepository 
{ 
    Book GetBookById(int id); 
    IQueryable<Book> GetAllBooks(); 
} 

public interface IPersonRepository 
{ 
    Person GetPersonById(int id); 
    IQueryable<Person> GetAllPeople(); 
} 

我實現IUnitOfWork如下:

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)。它顯示了類似的評價。它可能會給你一些想法。 – Steven

回答

8

使用DI容器作爲Service Locator can hardly be said to be good practice。除此之外,在解析接口時將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(); 
    } 
} 

即使有中DbContext沒有明確的共享,這可以通過容器進行配置。由於這個問題的上下文表明Castle Windsor是正在使用的容器,所以默認的生命週期已經是Singleton,所以你不需要來明確地設置它。隨着Castle Windsor,DbContext將自動在SqlUnitOfWork課程和這兩個存儲庫之間共享。

但是,您也可以明確配置的情況下被共享,就像這樣:

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

如果你使用其他的DI容器,該API會有所不同,但概念是相同的。

獎金的信息:我不知道的總體背景是什麼,但如果是在Web應用程序中使用和DbContext是實體框架或LINQ to SQL的情況下,正確的生命週期配置將改爲PerWebRequest,因爲這些上下文類都不是線程安全的:

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

對於構造函數注入來說有點不是最佳的;一個web請求可能只需要'SqlUnitOfWork.People.Get(322);'但是bookRepository的實例也可以創建(因爲它在構造函數中),即使它不需要 – Omu

+1

http://blog.ploeh.dk/2011/ 3月4日/ ComposeObjectGraphsWithConfidence.aspx –