这是我第一次实施更多领域驱动的设计方法。我决定尝试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