2011-08-04 12 views
5

tengo estas interfaces:Ayuda con Windsor y Repositorio y la Unidad de los patrones de trabajo

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(); 
} 

implemento IUnitOfWork de la siguiente manera:

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(); 
    } 
} 

Las implementaciones de IBookRepository y IPersonRepository utiliza un constructor que toma una DbContext como parámetro, y este DbContext se crea en el SqlUnitOfWork (código anterior) y paso este parámetro utilizando una sobrecarga del método Resolve.

Mi pregunta es, ¿es esta la manera correcta de hacerlo? ¿Es esta una buena practica?

Gracias!

+0

Eche un vistazo a [este artículo] (http://bit.ly/bF7jL3). Muestra un apprac similar. Puede darte algunas ideas. – Steven

Respuesta

8

Usando un contenedor DI como Service Locator can hardly be said to be good practice. Además de eso, pasar el DbContext al contenedor, mientras que la resolución de una interfaz es una abstracción Leaky porque implica que saber algo acerca de la aplicación concreta que no se debe.

En lugar de eso, recomiendo Constructor inyección, que sería algo parecido a esto:

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(); 
    } 
} 

A pesar de que no hay intercambio explícito de DbContext, esto se puede configurar a través del contenedor. Como el contexto de esta pregunta indica que Castle Windsor es el contenedor que se utiliza, la duración predeterminada es Singleton, por lo tanto, no tiene para configurarlo explícitamente. Con Castle Windsor, el DbContext se compartirá automáticamente entre la clase SqlUnitOfWork y ambos repositorios.

Sin embargo, también se puede configurar de forma explícita el contexto para ser compartida, así:

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

Si se va a usar otro DI de contenedores, la API sería diferente, pero el concepto es el mismo.

información Bono: No sé lo que es el contexto general, pero si esto es para ser utilizado en una aplicación web y DbContext es un marco de la entidad o LINQ a SQL contexto, la configuración correcta sería la vida en lugar de estar PerWebRequest ya que ninguna de esas clases de contexto es segura para subprocesos:

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

no es un poco no óptimo con inyecciones de constructor; una solicitud web sólo puede ser que necesite 'SqlUnitOfWork.People.Get (322);' pero bookRepository ejemplo, para que también ha creado (primo es en el constructor), a pesar de que no se necesita – Omu

+1

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

Cuestiones relacionadas