這是我第一次實施更多領域驅動的設計方法。我決定嘗試Onion Architecture,因爲它專注於域名而不是基礎設施/平臺等。洋蔥架構,工作單元和通用存儲庫模式
爲了抽象的實體框架的時候,我已經創建了一個通用倉庫與工作實施的單位。
的IRepository<T>
和IUnitOfWork
接口:
IRepository<T>
public interface IRepository<T>
{
void Add(T item);
void Remove(T item);
IQueryable<T> Query();
}
public interface IUnitOfWork : IDisposable
{
void SaveChanges();
}
實體框架的實現和IUnitOfWork
:
public class EntityFrameworkRepository<T> : IRepository<T> where T : class
{
private readonly DbSet<T> dbSet;
public EntityFrameworkRepository(IUnitOfWork unitOfWork)
{
var entityFrameworkUnitOfWork = unitOfWork as EntityFrameworkUnitOfWork;
if (entityFrameworkUnitOfWork == null)
{
throw new ArgumentOutOfRangeException("Must be of type EntityFrameworkUnitOfWork");
}
dbSet = entityFrameworkUnitOfWork.GetDbSet<T>();
}
public void Add(T item)
{
dbSet.Add(item);
}
public void Remove(T item)
{
dbSet.Remove(item);
}
public IQueryable<T> Query()
{
return dbSet;
}
}
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
private readonly DbContext context;
public EntityFrameworkUnitOfWork()
{
this.context = new CustomerContext();;
}
internal DbSet<T> GetDbSet<T>()
where T : class
{
return context.Set<T>();
}
public void SaveChanges()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
的客戶庫:
public interface ICustomerRepository : IRepository<Customer>
{
}
public class CustomerRepository : EntityFrameworkRepository<Customer>, ICustomerRepository
{
public CustomerRepository(IUnitOfWork unitOfWork): base(unitOfWork)
{
}
}
使用庫ASP.NET MVC控制器:
public class CustomerController : Controller
{
UnityContainer container = new UnityContainer();
public ActionResult List()
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();
return View(customerRepository.Query());
}
[HttpPost]
public ActionResult Create(Customer customer)
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();;
customerRepository.Add(customer);
unitOfWork.SaveChanges();
return RedirectToAction("List");
}
}
依賴注入的統一:
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>();
container.RegisterType<ICustomerRepository, CustomerRepository>();
解決方案:
問題?
存儲庫實現(EF代碼)是非常通用的。這一切都坐在
EntityFrameworkRepository<T>
班。具體模型存儲庫不包含任何這種邏輯。這使我無法編寫大量冗餘代碼,但可能會犧牲靈活性?ICustomerRepository
和CustomerRepository
類基本上是空的。他們純粹是爲了提供抽象。據我瞭解,這符合Onion架構的願景,即基礎架構和平臺相關代碼位於系統外部,但空類和空接口感覺不對?要使用不同的持久性實現(比如說Azure表存儲),那麼需要創建一個新的
CustomerRepository
類並繼承AzureTableStorageRepository<T>
。但是這可能會導致冗餘代碼(多個CustomerRepositories)?這種效果如何嘲笑?另一個實現(比如Azure表存儲)對跨國支持有限制,因此AzureTableStorageUnitOfWork類在此上下文中不起作用。
這樣做有什麼其他問題嗎?
(我已經採取了我的大部分靈感來自this post)
通過對IoC容器進行依賴性,您正在使用[service locator anti-pattern](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/)。相反,你應該註冊一個工廠類來注入你的控制器。一些IoC容器可以以'Func'依賴關係 –
AlexFoxGill