2015-11-03 63 views
0

我使用以下Ninject相关的NuGet包在MVC 5的WebAPI应用:通过ToFactory()生成的工厂创建的对象的控制寿命

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(); 
} 

我已经安装使用ToFactory()Ninject.Extensions.Factory的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生成的工厂(动态代理)相同的实例。

问题:有没有办法来改变/控制此行为,并设置了“一生”,如瞬态PerThread等为实例“CreateRepository”回报?

在这种特殊情况下,可能会在多个线程上异步处理任务,并且存储库不是线程安全的,因此从“CreateRepository”返回的实例的单例行为是不可取的。

+1

你有'Ninject.Extensions.ContextPresevation'安装吗? – BatteryBackupUnit

+0

不,我没有安装 –

回答

1

我不确定你要实现什么,但是你看到的结果是相当期望的,因为你的TaskRunner绑定为Singleton(这样构造一次),并且你在TaskRunner构造函数中检索你的仓库,一次,所以回购总是同一个实例。请注意,无论您如何绑定IRepository和IRepositoryFactory,都会发生这种情况,请参阅Mark Seemann的Captive Dependency帖子以了解详细信息http://blog.ploeh.dk/2014/06/02/captive-dependency/

实际上,如果您需要在构造函数中创建回购,您可以只注入IRepository本身。工厂扩展的力量在于,它允许在运行时解决实例,而不是构建时间。例如,如果您的TaskRunner具有Run()方法,则可以在其中创建存储库,因此每个要运行的任务都可以拥有自己的实例。

+0

好点。我过分简化了这个例子。实际上我想为repo工厂(在ctor中)保留一个单例,但是在Run()方法中解析不同的存储库,因为Run() )将是多线程的。我相信我注意到“CreateRepository”将始终返回相同的回购实例。然后我安装了“ContextPreservationExtension”,它似乎提供了所需的行为I.e. CreateRepository现在会在每次调用时返回不同的repo实例。 –