在嵌套/子容器中Transient真正是瞬态的任何DI容器?

时间:2015-09-16 17:52:53

标签: c# dependency-injection inversion-of-control ioc-container

我有一个要求是我需要一些我的域的实例在我选择的范围内保持不变。这些实例是一个例外,规范应该是每次域请求时所有实例都是新的。 (瞬态寿命应该起作用的方式)

问题是我找不到以这种方式工作的DI容器。

我测试了Castle Windsor和StructureMap。

在StructureMap中,你可以

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

现在默认情况是实例在嵌套容器的整个生命周期中存在。如果你想要我想要的行为,你需要注册所有应该是真正短暂的类型,如

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

这不起作用,我希望默认行为是另一种方式。那么你们是否知道以这种方式工作的IoC,或者可以配置以便默认行为是这样的。

编辑:对于好奇的人,您可以使用结构图https://github.com/AndersMalmgren/FreePIE/blob/MoveToStructureMap/FreePIE.Core/Common/StructureMap/StructureMapScopedContext.cs查看此工作分支。您可以使用界面IScopedContext<TEntryPoint>在域中创建范围生命周期。问题在于它无法“限制”生命周期,而不是短暂的生命时间。要获得真实的瞬态寿命,您需要将其设置为始终唯一。我已经用这个小hacky帮手

为未注册的具体类型解决了这个问题

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

1 个答案:

答案 0 :(得分:2)

Simple Injector支持variety of scoped lifestyles而无需子容器。默认情况下,Simple Injector将在任何生命周期范围内返回 Transient ,除非明确指示其他方式。以下是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);
    }
}