【发布时间】:2010-10-01 04:23:46
【问题描述】:
现在我正在尝试找出一种更智能的方法,在此过程中,我设法在一天内使用一整瓶 excedrin。
假设我有一个类似 IRepository 的接口。
public interface IRepository<T>
{
T Get(int id);
void Add(T value);
void Update(T value);
void Delete(T value);
...
}
假设我有一个像
这样的实现public class NHibernateRepository<T>
{
...
}
现在,一切都很好,我可以对存储库执行所有基本操作以支持所有 CRUD 功能,但我可能需要专门的操作,所以假设我有一个这样的接口:
public interface IUserRepository : IRepository<User>
{
IList<User> GetUsersByRole(Role role);
}
还有这样的实现:
public class UserRepository : NHibernateRepository<User>, IUserRepository
{
....
}
好的,这就是基本设置,现在我还想做一件事。我想要透明地进行日志记录和事务以及类似的事情。所以我想做的是使用像 Castle Windsor 或 StructureMap 这样的依赖注入框架,这样当我请求 IRepository 时,我会用 LoggingRepository 和 TransactionRepository 包装它,它们都实现了 IRepository。
所以,我想做的是这样的:
IUserRepository repository = container.Resolve< IUserRepository>();
并让它返回一个包含在 Logging 和 Transaction 装饰器中的用户存储库,但我想不出一种可行的方法。我能想到让它工作的唯一方法是像这样实现 UserRepository:
public class UserRepository : DecoratorRepository<T>, IUserRepository
{
protected IRepository<T> Repository { get; set; }
public UserRepository(IRepository<T> innerRepository)
{
Repository = innerRepository;
}
}
这意味着我们将使用依赖注入来创建一个修饰的存储库并将其传递给 UserRepository 的构造函数,然后将其用作我们对其运行操作的存储库。这可行,但我仍然认为它不理想。
所以,我的问题是,我是否正确,这是唯一的方法,还是我没有正确理解这一点,或者只是错过了一些东西。另外,如果你之前遇到过这个问题,你是怎么解决这个问题的?
【问题讨论】:
-
嗨,达伦。我对您如何解决这个问题非常感兴趣,因为我的情况与使用自定义查询方法关闭开放通用 Repository
类的自定义存储库和可以轻松装饰的简单开放通用存储库的情况完全相同。请告诉我…… -
@MagnusBackeus 我最终没有做修饰的存储库,因为我认为我会使用它们的大多数事情最终都用于代码的其他方面(例如事务转到
UnitOfWork)。我几乎到处都注入了通用存储库,包括当我引入像IUserRepository这样的专用存储库时,它只会注入IRepository<User>。但是,我从不创建与通用存储库冲突的类(即我不会创建@ 987654330@),我总是介绍新界面。 -
有趣的方法......我已经在我的脑海中走了这条路,但总是停止思考“我应该把自定义存储库方法放在哪里”的问题,比如上面的 IList
GetUsersByRole(Role role)。你通过其他接口来表达这些新的扩展方法?? -
是的,我总是引入
IUserRepository,然后注入IRepository<User>。 -
我之前还添加了不同的对象,例如 Query 对象,因此可能是您添加的其他对象与方法,具体取决于您在做什么。
标签: c# dependency-injection domain-driven-design repository-pattern decorator-chaining