1

我有一個要求,我需要我的域的一些實例在我選擇的範圍內保持不變。這些實例是一個例外,並且規範應該是每次域請求時所有實例都是新的。 (短暫的生命時間應該工作的方式)在嵌套/子容器期間瞬態是否真的瞬態的任何DI容器?

問題是我無法找到這樣工作的DI容器。

我測試了Castle Windsor和StructureMap。

在StructureMap你做

using(var nested = container.GetNestedContainer()) 
{ 
    var whatEver = nested.GetInstance<IWhatEver>(); 
} 

默認現在是實例嵌套容器的整個生命過程中生活。如果你想我要的行爲,你需要註冊應真正瞬態像

config 
    .For<IMyTransientType>() 
    .LifecycleIs(new UniquePerRequestLifecycle()) 
    .Use<MyTransientType>(); 

這是行不通的所有類型,我想要的默認行爲是周圍的其他方式。所以你們知道這樣工作的IoC,或者可以配置這樣的默認行爲就是這樣。

編輯:爲了好奇,你可以在這裏使用Structure map,https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/StructureMapScopedContext.cs查看這個工作分支。你可以使用界面IScopedContext<TEntryPoint>創建一個有限的生命週期。問題在於,它忽略了「範圍」的生命期而不是短暫的生命期。要獲得真正的短暫生活時間,您需要將其設置爲始終唯一。我曾與這個小哈克幫手

https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/ConcreteTypeConventionScanner.cs

從DI引導程序解決它註銷的具體類型我再做

var assebmlies = container 
    .GetInstance<IPluginDataSource>() 
    .ListAllPluginTypes() 
    .GroupBy(t => t.Assembly) 
    .Select(g => g.Key); 

assebmlies.ForEach(a => container.Configure(config => config.Scan(scan => 
{ 
    scan.Assembly(a); 
    scan.Convention<ConcreteTypeRegistrationConvention>(); 
}))); 
+0

作爲一個經驗法則,Castle Wind sor可以配置爲做任何你想做的事情。如果沒有別的,它可以讓你寫自己的習慣生活方式。有關詳細信息,請參見[我的書](http://amzn.to/12p90MG)的第10.2.3節。 –

+3

請分享那些應該在您的範圍內緩存的「[您的]域名實例」的詳細信息。請使用此類「實例」的代碼示例更新您的問題。 – Steven

+0

非常複雜的域名。但總體思路是我們有生命期範圍(類似於Web api請求範圍)。在此範圍內,我希望默認值始終是唯一的,而不是相反。 – Anders

回答

2

Simple Injector提供了一個variety of scoped lifestyles支持,無需子容器。默認情況下,簡單注射器將在任何生命週期範圍內返回瞬態,除非明確指示另有說明。這裏有3次試驗,以證明功能...

瞬態沒有作用域

[Fact] 
public void GetInstance_NoSpecificLifestyleOutsideOfAnyScope_IsAlwaysANewInstance() 
{ 
    var container = new Container(); 
    container.Register<IService, Service>(); 
    container.Verify(); 

    var a = container.GetInstance<IService>(); 
    var b = container.GetInstance<IService>(); 
    Assert.NotSame(a, b); 
} 

非用明確的生活方式註冊瞬態IService

[Fact] 
public void GetInstance_SpecificLifestyleWithinAScope_IsTheSameInstance() 
{ 
    var container = new Container(); 
    container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle(); 
    container.Register<IService, Service>(Lifestyle.Scoped); 
    container.Verify(); 

    using (container.BeginLifetimeScope()) 
    { 
     var a = container.GetInstance<IService>(); 
     var b = container.GetInstance<IService>(); 
     Assert.Same(a, b); 
    } 
} 

瞬態IService解決一生範圍內

[Fact] 
public void GetInstance_NoSpecificLifestyleWithinAScope_IsAlwaysANewInstance() 
{ 
    var container = new Container(); 
    container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle(); 
    container.Register<IService, Service>(); 
    container.Verify(); 

    using (container.BeginLifetimeScope()) 
    { 
     var a = container.GetInstance<IService>(); 
     var b = container.GetInstance<IService>(); 
     Assert.NotSame(a, b); 
    } 
} 
+0

好的,會查看該庫。它也需要支持Func 工廠。那不是問題?編輯:看起來好像你們都很快 – Anders

+0

嗯,我有一個特殊的要求,我需要將範圍創建者註冊爲特定的界面,以便任何人都可以處理範圍。我用StructureMap做了這樣的事情,你知道用SimpleInjector怎麼做嗎? https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/StructureMapScopedContext.cs#L20 – Anders

+0

你可以在['container.BeginLifetimeScope()'](https:// simpleinjector.readthedocs.org/en/latest/lifetimes.html#perlifetimescope),但是當他們擁有的範圍被處置時,你會期望發生什麼?您是否可以在SO或[forum](https://github.com/simpleinjector/SimpleInjector/issues)上將需求而不是解決方案定義爲新問題?我相信會有一個兼容的解決方案.... – qujck