0

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.

Community
  • 1
  • 1
Abhijeet Patel
  • 6,562
  • 8
  • 50
  • 93

1 Answers1

1

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.

ovolko
  • 2,777
  • 2
  • 21
  • 26
  • Good point.I oversimplified the example.In truth I'd like to maintain a singleton for the repo factory (in the ctor) but resolve distinct repositories in the Run() method since Run() will be multi threaded. I believe I noticed that "CreateRepository" would always return the same repo instance. I then installed the "ContextPreservationExtension" which seems to provide the desired behavior I.e. CreateRepository now return distinct repo instances on each invocation. – Abhijeet Patel Nov 14 '15 at 19:27