控制由ToFactory()

时间:2015-11-03 03:42:03

标签: ninject ninject.web.mvc ninject-extensions

我在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;是不可取的。

1 个答案:

答案 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()方法,则可以在其中创建存储库,因此要运行的每个任务都可以拥有自己的实例。