C# 在嵌套/子容器期间,瞬态是真正瞬态的任何DI容器?

C# 在嵌套/子容器期间,瞬态是真正瞬态的任何DI容器?,c#,dependency-injection,inversion-of-control,ioc-container,C#,Dependency Injection,Inversion Of Control,Ioc Container,我有一个要求,就是我需要我的域的一些实例在我选择的范围内保持不变。这些实例是一个例外,规范应该是每次域请求它们时,所有实例都是新的。(短暂生命周期的工作方式) 问题是我找不到这样工作的DI容器 我已经测试了温莎城堡和结构图 在StructureMap中,您可以 using(var nested = container.GetNestedContainer()) { var whatEver = nested.GetInstance<IWhatEver>(); } 使用(var

我有一个要求,就是我需要我的域的一些实例在我选择的范围内保持不变。这些实例是一个例外,规范应该是每次域请求它们时,所有实例都是新的。(短暂生命周期的工作方式)

问题是我找不到这样工作的DI容器

我已经测试了温莎城堡和结构图

在StructureMap中,您可以

using(var nested = container.GetNestedContainer())
{
   var whatEver = nested.GetInstance<IWhatEver>();
}
使用(var nested=container.GetNestedContainer())
{
var whather=nested.GetInstance();
}
默认情况下,实例将在嵌套容器的整个生命周期内存在。如果你想要我想要的行为,你需要注册所有类型,这些类型应该是真正的瞬态的

config
   .For<IMyTransientType>()
   .LifecycleIs(new UniquePerRequestLifecycle())
   .Use<MyTransientType>(); 
config
.对于()
.LifecycleIs(新的UniquePerRequestLifecycle())
.使用();
这将不起作用,我希望默认行为是相反的。你们知道这样工作的IoC吗,或者可以配置成这样的默认行为

编辑:出于好奇,您可以使用结构图在此处查看此工作分支。您可以使用接口
IScopedContext
在域中创建作用域生存期。问题是,它将使用“限定范围”的生存期而不是瞬态生存期。要获得真实的短暂生命时间,您需要将其设置为“始终唯一”。我用这个小帮手解决了未注册具体类型的问题

从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>();
})));
var assebmlies=容器
.GetInstance()
.ListAllPluginTypes()
.GroupBy(t=>t.Assembly)
.选择(g=>g.Key);
assebmlies.ForEach(a=>container.Configure(配置=>config.Scan(扫描=>
{
扫描组装(a);
scan.Convention();
})));
提供对的支持,而不需要子容器。默认情况下,除非明确指示,否则简单喷油器将在任何寿命范围内返回瞬态。这里有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);
}
瞬态
iSeries设备
在生存期范围内解决

[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);
    }
}
[事实]
public void GetInstance\u NoSpecificLiFestyleWithInScope\u始终是SANEWINSTANCE()
{
var container=新容器();
container.Options.DefaultScopedLifestyle=new LifetimeScopeLifestyle();
container.Register();
container.Verify();
使用(container.BeginLifetimeScope())
{
var a=container.GetInstance();
var b=container.GetInstance();
断言。不相同(a,b);
}
}

根据经验,可以将Castle Windsor配置为执行您希望它执行的任何操作。如果没有别的,它可以让你写下你自己的定制生活方式。有关详细信息,请参阅的第10.2.3节。请共享在您的作用域期间应缓存的“域实例”的详细信息。请用此类“实例”的代码示例更新您的问题。相当复杂的域。但总体思路是我们有生命周期范围(类似于WebAPI请求范围)。在此范围内,我希望默认值始终是唯一的,而不是相反。使用更多信息更新您希望在范围内暂时更新,但在范围外需要什么:singleton?Nice,将查看该库。它还需要支持Func工厂。这不是问题吗?编辑:很好,看起来你们很快,嗯,我有一个特殊的要求,我需要注册范围创建者作为一个特定的接口,这样任何人都可以处理范围。我是用StructureMap做的,你知道如何用SimpleInjector做吗?您可以围绕它创建一个抽象,但是当当前解析的实例拥有的范围被释放时,您会期望它们发生什么呢?您是否可以将需求而不是解决方案定义为一个新问题,或者是SO问题,或者是解决方案问题?我相信会有一个兼容的解决方案……需要将抽象添加到范围中,这样就没有区别了我可以理解“当前范围中的任何子项都应该能够结束范围”的概念,但是想象一下,您在该范围中有一个
IDisposable
对象;任何
IDisposable
对象都应该随作用域一起立即被
处理
,并且您有一个很难追踪的bug。在对象图中结束作用域是一件危险的事情。“仅仅因为你可以,并不意味着你应该”——)
[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);
    }
}