我在MVC 5 WebAPI应用程序中使用以下与Ninject相关的nuget包:
Ninject.MVC5
Ninject.Extensions.Factory
ninject.extensions.conventions
我有一个简单的存储库和相应的工厂类,如下所示:
public interface ITaskRunner
{
void Run();
}
public interface IRepository<T> where T: class
{
T[] GetAll();
}
public interface IRepositoryFactory<T> where T: class
{
IRepository<T> CreateRepository();
}
我已经使用 Ninject.Extensions.Factory 中的 ToFactory()设置了Ninject绑定,如下所示:
kernel.Bind<ITaskRunner>().To<TaskRunner>().InSingletonScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
kernel.Bind<IRepositoryFactory<Contact>>().ToFactory();
我在以下课程中使用工厂:
public class TaskRunner : ITaskRunner
{
//MyTask is a simple POCO class(not shown for brevity)
IRepositoryFactory<MyTask> repoFactory = null;
IRepository<MyTask> repo = null;
public TaskRunner(IRepositoryFactory<MyTask> repoFactory)
{
this.repoFactory = repoFactory;
repo = repoFactory.CreateRepository();
}
//implementation elided
}
我注意到对 repoFactory.CreateRepository()的调用总是返回Ninject生成的工厂(动态代理)的相同实例。
问题:有没有办法更改/控制此行为并设置&#34;生命周期&#34;例如 Transient , PerThread 等对于&#34; CreateRepository&#34;的实例。返回?
在这种特殊情况下,任务可能在多个线程上异步处理,并且存储库不是线程安全的,因此实例的单例行为从&#34; CreateRepository&#34;是不可取的。
答案 0 :(得分:1)
我不确定您要实现的目标,但您看到的结果非常令人期待,因为您的TaskRunner绑定为Singleton(如此构造一次),并在TaskRunner构造函数中检索您的存储库,发生一次,所以repo始终是同一个实例。请注意,无论您如何绑定IRepository和IRepositoryFactory,都会发生这种情况,请参阅Mark Seemann的Captive Dependency帖子了解详细信息http://blog.ploeh.dk/2014/06/02/captive-dependency/。
事实上,如果你需要在构造函数中创建repo,你可以自己注入IRepository。 Factory扩展的强大之处在于它允许在运行时处解析实例,而不是构建时间。例如,如果您的TaskRunner具有Run()方法,则可以在其中创建存储库,因此要运行的每个任务都可以拥有自己的实例。