我有一个包含多个存储库的服务(通过ninject绑定):
Bind<IRepository<User>>().To<Repository<User>>().InRequestScope();
由于服务在构造函数中注入了太多依赖项,因此我决定使用RepositoryProvider
:
public class RepositoryProvider : IRepositoryProvider
{
private readonly Func<Type, object> factory;
public RepositoryProvider(Func<Type, object> factory)
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
this.factory = factory;
}
public IRepository<T> GetRepository<T>() where T : class
{
Type type = typeof(T);
object repository = factory(type);
if (repository != null)
{
return (IRepository<T>)repository;
}
string message = string.Format(CultureInfo.InvariantCulture, "No repository found for {0}", type.Name);
throw new NotImplementedException(message);
}
}
通过Ninject注册存储库工厂:
Func<Type, object> repositoryFactory = type =>
{
Type repositoryType = typeof(IRepository<>).MakeGenericType(type);
return Kernel.Get(repositoryType);
};
这提供了一个通用存储库的实例:
public class Repository<T> : IRepository<T>, IDisposable where T : class
{
private IEntities context;
public Repository(IEntities context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
this.context = context;
}
public IQueryable<T> GetAll()
{
return context.GetDbSet<T>();
}
#region IDisposable
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (disposing)
{
context.Dispose();
context = null;
}
}
#endregion
}
现在,当我直接在服务中注入存储库时,我看到在请求之后立即调用Dispose()
方法(当我设置断点时)。但是当我使用提供程序时,我根本看不到Dispose()
。
这可能是什么原因?我是否已完成所有设置以确保ninject调用Dispose()
?
我看到其他答案提到“OncePerWebRequest”模块,但似乎无法找到任何关于此的文档,也不知道这是否有必要。
答案 0 :(得分:1)
当您从ctor注入更改为工厂创建时,您更改了&#34; time&#34;实例是createad。由于InRequestScope()
以前有效,我建议在HttpContext.Current
无效/为空的位置创建工厂创建的实例。
请注意,从ctor注入更改为工厂创建,您已经打开了一个新问题:您现在正在使用服务位置,并且您的对象图不是(必然)从根目录创建的走。还see Mark Seeman's blog post on service locator。
修复&#34;所有&#34;一次性问题我建议稍微调整一下存储库。与IRepository<T>
之类的方法T GetAll()
不同,为什么不将其更改为IRepository
和T GetAll<T>()
等方法。这样,您只需要一个存储库实例:
public class Repository : IRepository, IDisposable
{
private IEntities context;
public Repository(IEntities context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
this.context = context;
}
public IQueryable<T> GetAll<T>()
where T : class
{
return context.GetDbSet<T>();
}
#region IDisposable
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (disposing)
{
context.Dispose();
context = null;
}
}
#endregion
}