使用存储库以工作单元为单位进行依赖注入

我想创建一个工作单元类,以类似于此方法的方式包装存储库。

我遇到的问题是尝试通过使用IRepository接口替换示例中的通用存储库来实现依赖项注入。在链接文章的uow中,他们使用getters检查存储库是否已实例化,如果尚未实例化,则将其实例化。

public GenericRepository<Department> DepartmentRepository

{

get

{

if (this.departmentRepository == null)

{

this.departmentRepository = new GenericRepository<Department>(context);

}

return departmentRepository;

}

}

这是紧密耦合的。

我可以看到两种解决方法。

  1. 使用构造函数注入。
  2. 使用二传手注射。

1的问题是,如果我注入了所有存储库,则即使我不在该特定工作单元实例中使用它们,也必须实例化每个存储库。因此,这样做会产生开销。我在想使用一个数据库范围的工作单元类,因此这将导致大量不必要的实例化和一个巨大的构造函数。

2的问题在于,很容易忘记设置并以空引用异常结束。

在这种情况下,是否有任何最佳做法?还有我错过的其他选择吗?

我只是进入依赖注入,并完成了我可以在该主题上找到的所有研究,但是我可能缺少一些关键的东西。

回答:

解决此问题的方法不是通过容器注入使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 classes

container.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,并建议您在此处和此处阅读这两篇文章。

以上是 使用存储库以工作单元为单位进行依赖注入 的全部内容, 来源链接: utcz.com/qa/399276.html

回到顶部