讓我從我當前的設置開始,然後解釋我想實現的目標。我們使用NHibernate並試圖用Ninject實現IRepository/IUnitOfWork模式。理想情況下,它應該適用於任何使用代碼的應用程序,無論是ASP.Net,WCF還是其他。ninject注入iunitofwork到存儲庫作用域屬性
IUnitOfWork
public interface IUnitOfWork
{
object Add(object obj);//all other supported CRUD operations we want to expose
void Commit();
void Rollback();
}
的UnitOfWork
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();
}
}
IRepository
public interface IRepository<TEntity, TId> where TEntity : class
{
TId Add(TEntity item);//add other missing CRUD operations
}
GenericRepository
public class GenericRepository<TEntity, TId> : IRepository<TEntity, TId>
where TEntity : class
{
public TId Add(TEntity item)
{
throw new NotImplementedException();
}
}
我使用Ninject作爲我的IOC容器。目標是在創建UnitOfWork的生命週期中重複使用相同的IUnitOfWork。無論調用的應用程序是什麼,我都希望實現的生命週期能夠正常工作,否則我會像使用大多數在線提示一樣使用InRequestScope。 我能夠做這樣的事:
//constructor
public MyService(IUnitOfWork uow, IRepository<User, int> userRepo, IRepository<Cat, int> catRepo)
{
_uow = uow; _userRepo = userRepo; _catRepo = catRepo;
}
//method in same class
public 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相同的UnitOfWork函數,無論它實際上可能有多少層。
但是我想要做的就是將IUnitOfWork完全隱藏起來。我寧願提供一些可放置在方法之上的TransactionAttribute,它將在條目上創建IUnitOfWork,並將同一實例注入到TransactionAttribute範圍內的所有將來的IUnitOfWork請求中。它會相應地提交和回滾。所以上面的代碼會變成這樣:
//constructor
public 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);
}
是否有任何形式的結合設置我能做到這將使我來標記與[交易]的方法也是這樣嗎?我願意對IUnitOfWork和IRepository進行一些小的重構,而服務層代碼只是廢料代碼,所以我可以在那裏非常靈活。
我們目前使用'PostSharp'(V2.1可悲)在其他組件,所以我知道我會用它來實現AOP。我的想法是,我的方面的OnEntry會開始一個新的'UnitOfWork'(我會忽略嘗試附加到現有的),但我如何確保創建的'UnitOfWork'是注入每個' IRepository'?我是否需要通過將方面的'UnitOfWork'粘貼到某種上下文機制(ThreadLocal/SynchronizationContext,就像您所提到的)? – cjablonski76 2014-10-31 13:13:14
既然(至少這就是我干涉的內容),你不能也不想將「Session」的生命週期與使用它的對象的生命週期聯繫起來,你確實需要使用像ThreadLocal這樣的上下文機制或SynchronizationContext。 – BatteryBackupUnit 2014-10-31 13:44:33
如果你不想使用這樣的上下文機制,每次執行DoSomeWork時都需要創建一個新的用戶回購,cat回購等。你可能最終會重新創建你的對象圖中相當大的一部分(取決於設計...)。有了上下文機制,你只能創建'Session',但你仍然需要這樣做(通過'IUnitOfWork.Begin()'或創建一個新的'IUnitOfWork'實例)。 – BatteryBackupUnit 2014-10-31 13:47:12