2015-11-03 61 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實例。 –