让我从当前的设置开始,然后解释我要实现的目标。我们正在使用NHibernate并尝试通过Ninject实现IRepository / IUnitOfWork模式。理想情况下,无论使用ASP.Net,WCF还是其他任何形式的代码,它都应该可以通用地工作。IUnitOfWorkpublic interface IUnitOfWork{ object Add(object obj);//all other supported CRUD operations we want to expose void Commit(); void Rollback();}工作单位public class UnitOfWork : IUnitOfWork{ private readonly ISessionFactory _sessionFactory; private readonly ISession _session; private readonly ITransaction _transaction; public UnitOfWork(ISessionFactory sessionFactory) { _sessionFactory = sessionFactory; _session = _sessionFactory.OpenSession(); _transaction = _session.BeginTransaction(); } public object Add(object obj) { return _session.Save(obj); } public void Commit() { if(!_transaction.IsActive) {throw new Exception("some error");} _transaction.Commit(); } public void Rollback() { if (!_transaction.IsActive) { throw new Exception("some other error"); } _transaction.Rollback(); }}知识库public interface IRepository<TEntity, TId> where TEntity : class{ TId Add(TEntity item);//add other missing CRUD operations}通用存储库public class GenericRepository<TEntity, TId> : IRepository<TEntity, TId> where TEntity : class{ public TId Add(TEntity item) { throw new NotImplementedException(); }}我正在使用Ninject作为我的IOC容器。目标是在创建UnitOfWork的生命周期中重用相同的IUnitOfWork。我希望无论调用应用程序是什么,实现的生命周期都可以正常工作,否则我将像大多数在线建议一样使用InRequestScope。我能够做这样的事情://constructorpublic MyService(IUnitOfWork uow, IRepository<User, int> userRepo, IRepository<Cat, int> catRepo){ _uow = uow; _userRepo = userRepo; _catRepo = catRepo;}//method in same classpublic void DoSomeWork(){ _userRepo.Add(someUser); _catRepo.Add(someCat); _uow.Commit(); //rollback on error}我的绑定设置如下:Bind<IUnitOfWork>.To<UnitOfWork>().InCallScope();Bind(typeof(IRepository<,>)).To(typeof(GenericRepository<,>));并且此绑定配置实际上适用于上述MyService,它将在构造函数中创建一次UnitOfWork,并且还将对IRepo impls使用相同的UnitOfWork,无论它们实际上可能向下分层了几层。但是我想做的是将IUnitOfWork完全隐藏在应用程序之外。我宁愿提供一些放置在方法顶部的TransactionAttribute,它将在入口处创建IUnitOfWork,并且同一实例将注入到TransactionAttribute范围内对IUnitOfWork的所有将来请求中。并且它将相应地负责提交和回滚。因此,先前的代码将变成这样://constructorpublic MyService(IRepository<User, int> userRepo, IRepository<Cat, int> catRepo){ _uow = uow; _userRepo = userRepo; _catRepo = catRepo;}//method in same class[Transaction]public void DoSomeWork(){ _userRepo.Add(someUser); _catRepo.Add(someCat);}有什么绑定设置我可以做的,可以使我用[Transaction]这样的方法标记方法吗?我愿意对IUnitOfWork和IRepository的内容进行一些小规模的重组,并且Service层代码只是简单的代码,因此我可以在其中灵活一点。 最佳答案 首先,注入将不适用于[Transaction]public void DoSomeWork(){ _userRepo.Add(someUser); _catRepo.Add(someCat);}毕竟,容器不知道您将要调用哪种方法以及何时调用它。进一步介绍一下,因为您希望它与WebApps,WCF等一起工作,或者做一些石英工作:您必须决定是否要绑定IUnitOfWork / Repository / NHibernate 到使用它的对象的生命周期(例如Session),或者如果您希望服务寿命更长(例如单例)并为方法调用创建新的NHibernate MyService,例如:[Transaction]public void DoSomeWork(){ _userRepo.Add(someUser); _catRepo.Add(someCat);}实际上,这可以通过AOP使用Fody或PostSharp来实现。另外,您也可以考虑使用装饰器模式来实现此目的(例如,参见here)。但是,如果我没记错的话,ninject当前缺乏一些支持easz装饰器处理的功能。除了Session属性,您还可以从显式控制所有内容开始:public interface IUnitOfWork{ IUnitOfWorkSession Begin(); // starts a session and transaction}public interface IUnitOfWorkSession : IDisposable{ void Commit(); void Dispose(); // performs rollback in case no commit was performed}由于您将需要访问其他对象中的nhibernate [Transaction],例如Session和_userRepo,因此,您还需要一种独立于容器访问_catRepo的方法,因为它与如何操作无关/当实例化对象时。当然,您可以像这样传递它:public void DoSomeWork(){ using(IUnitOfWorkSession session = _unitOfWork.Begin()) { _userRepo.Add(session, someUser); _catRepo.Add(session, someCat); session.Commit(); }}但这不是很酷。因此,相反,您将需要使用Session之类的东西(如果您正在使用async / await,则可能会出现问题),或者使用ThreadLocal-本地存储。现在,如果您能做到这一点,您可以考虑进行AOP。AOP将处理两个问题:获得对IUnitOfWork的访问权限。可以通过将其作为附加的ctor参数进行编织来完成或者它可以检查是否已经存在一个,如果存在,则可以使用这个,如果不存在,它可以将参数抛出或编织到...用上面的相同代码包装装饰方法:public void DoSomeWork(){ using(IUnitOfWorkSession session = _unitOfWork.Begin()) // weave this { _userRepo.Add(session, someUser); _catRepo.Add(session, someCat); session.Commit(); // weave this }}关于c# - ninject将iunitofwork注入(inject)到存储库范围内的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26665351/ 10-11 03:41