解决此问题的方法不是通过容器注入使
UnitOfWork创建每个对象负责
Repository,而是使每个对象都有责任
Repository确保
UnitOfWork在实例化时知道其存在。
这将确保
- 您
UnitOfWork
不需要为每个新的更改Repository
- 您没有使用服务定位器(很多人认为这是一种反模式)
最好用一些代码来演示-我使用SimpleInjector,因此示例基于此:
从
Repository抽象开始:
public interface IRepository { void Submit();}public interface IRepository<T> :IRepository where T : class { }public abstract class GenericRepository<T> : IRepository<T> where T : class { }和
UnitOfWork
public interface IUnitOfWork{ void Register(IRepository repository); void Commit();}每个人都
Repository必须向进行
注册
UnitOfWork,这可以通过更改抽象父类
GenericRepository以确保完成来完成:
public abstract class GenericRepository<T> : IRepository<T> where T : class{ public GenericRepository(IUnitOfWork unitOfWork) { unitOfWork.Register(this); }}每个实数都
Repository继承自
GenericRepository:
public class Department { }public class Student { }public class DepartmentRepository : GenericRepository<Department> { public DepartmentRepository(IUnitOfWork unitOfWork): base(unitOfWork) { }}public class StudentRepository : GenericRepository<Student>{ public StudentRepository(IUnitOfWork unitOfWork) : base(unitOfWork) { }}添加的物理实现,
UnitOfWork您就可以设置好:
public class UnitOfWork : IUnitOfWork{ private readonly Dictionary<string, IRepository> _repositories; public UnitOfWork() { _repositories = new Dictionary<string, IRepository>(); } public void Register(IRepository repository) { _repositories.Add(repository.GetType().Name, repository); } public void Commit() { _repositories.ToList().ForEach(x => x.Value.Submit()); }}可以将容器注册设置为自动选择的所有定义实例,
IRepository并在生命周期范围内注册它们,以确保它们在事务的生命周期中都有效:
public static class BootStrapper{ public static void Configure(Container container) { var lifetimeScope = new LifetimeScopeLifestyle(); container.Register<IUnitOfWork, UnitOfWork>(lifetimeScope); container.RegisterManyForOpenGeneric( typeof(IRepository<>), lifetimeScope, typeof(IRepository<>).Assembly); }}有了这些抽象和基于DI构建的体系结构,您就
UnitOfWork可以知道
Repository在任何服务调用中都已实例化的所有对象,并且可以通过编译时验证来确定所有存储库都已定义。您的代码可以扩展,但是可以修改。
要测试所有这些-添加这些类
public class SomeActivity{ public SomeActivity(IRepository<Department> departments) { }}public class MainActivity{ private readonly IUnitOfWork _unitOfWork; public MainActivity(IUnitOfWork unitOfWork, SomeActivity activity) { _unitOfWork = unitOfWork; } public void test() { _unitOfWork.Commit(); }}将这些行添加到
BootStrapper.Configure()
//register the test classescontainer.Register<SomeActivity>();container.Register<MainActivity>();
在代码行中放置一个断点:
_repositories.ToList().ForEach(x => x.Value.Submit());
最后,运行以下控制台测试代码:
class Program{ static void Main(string[] args) { Container container = new Container(); BootStrapper.Configure(container); container.Verify(); using (container.BeginLifetimeScope()) { MainActivity entryPoint = container.GetInstance<MainActivity>(); entryPoint.test(); } }}您会发现代码在断点处停止,并且您有一个处于活动状态的
IRepositoryready 实例,正在等待
Submit()数据库的任何更改。
您可以装饰UnitOfWork来处理事务等。此时,我将遵循强大的.NetJunkie,并建议您在此处和此处阅读这两篇文章。



