Abhijeet Patel
Abhijeet Patel

Reputation: 6878

Controlling lifetime of objects created by factory generated by ToFactory()

I am using the following Ninject related nuget packages in an MVC 5 WebAPI application:

Ninject.MVC5

Ninject.Extensions.Factory

ninject.extensions.conventions

I have a simple repository and a corresponding factory class like so:

public interface ITaskRunner
{
    void Run();
}
public interface IRepository<T> where T: class
{
    T[] GetAll();
}
public interface IRepositoryFactory<T> where T: class
{
    IRepository<T> CreateRepository();
}

I have setup the Ninject bindings using ToFactory() from Ninject.Extensions.Factory like so:

 kernel.Bind<ITaskRunner>().To<TaskRunner>().InSingletonScope();
 kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
 kernel.Bind<IRepositoryFactory<Contact>>().ToFactory();

I am using the factory in the following class:

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
}

I am noticing that the call to repoFactory.CreateRepository() always returns the same instance of the factory (dynamic proxy) that Ninject generates.

Question : Is there a way to change/control this behavior and set a "lifetime" such as Transient, PerThread etc. for the instance that "CreateRepository" returns?

In this particular case, tasks might be processed asynchronously on multiple threads and the repository is not thread safe and hence singleton behavior for the instance returned from "CreateRepository" is not desirable.

Upvotes: 0

Views: 274

Answers (1)

ovolko
ovolko

Reputation: 2797

I'm not sure what you are trying to achieve, but results you are seeing are quite expected because your TaskRunner is bound as Singleton (so constructed once), and you retrieve your repository in the TaskRunner constructor, which again happens once, and so repo is always the same instance. Note this happens regardless of how you bind IRepository and IRepositoryFactory, see Captive Dependency post by Mark Seemann for details http://blog.ploeh.dk/2014/06/02/captive-dependency/.

In fact, if you need to create repo in the constructor, you could just inject IRepository itself. The power of the Factory extension lies in the fact that it allows to resolve instances at runtime, not construction time. For example, if your TaskRunner has Run() method, you can create repository in it, so each task to run can have its own instance.

Upvotes: 1

Related Questions