You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StructureMap注入集合时重复IBar实例问题及解决方案问询

解决StructureMap中IFoo集合每个实例获取独立IBar实例的问题

我完全懂你的困扰——不能动全局的IBar配置(毕竟其他业务模块还依赖它当前的生命周期),但又得让每个IFoo实例都拿到独一份的Bar对象。下面给你几个实用的解决方案,按需选就行:

方案1:给每个IFoo实现单独配置依赖规则

这是最直接的做法,不用碰全局IBar的配置,只需要针对每个IFoo的实现类,明确告诉StructureMap:给这个类注入IBar的时候,每次都新建一个实例(也就是Transient生命周期)。

var container = new Container(_ => {
    _.Scan(x => {
        x.TheCallingAssembly();
        x.AddAllTypesOf<IFoo>();
    });
    // 全局IBar配置原封不动保留
    _.For<IBar>().Use<Bar>();

    // 为每个IFoo实现单独指定IBar的注入规则
    _.For<Foo1>().Ctor<IBar>().Is<Bar>().Transient();
    _.For<Foo2>().Ctor<IBar>().Is<Bar>().Transient();
});

这样一来,创建Foo1或Foo2时,StructureMap会专门为它们生成新的Bar实例,而其他地方请求IBar时,还是遵循原来的全局配置,不会影响现有业务。

方案2:用条件绑定批量处理所有IFoo实现

如果你的IFoo实现类很多,一个个配置太麻烦,那就用StructureMap的条件绑定功能——只要IBar是被IFoo的子类依赖的,就自动用Transient生命周期,其他场景依然沿用全局配置:

var container = new Container(_ => {
    _.Scan(x => {
        x.TheCallingAssembly();
        x.AddAllTypesOf<IFoo>();
    });

    // 全局IBar配置不变
    _.For<IBar>().Use<Bar>();

    // 核心规则:当IBar被IFoo的实现类依赖时,每次都新建实例
    _.For<IBar>()
        .When(context => context.ParentType?.IsAssignableTo(typeof(IFoo)) == true)
        .Use<Bar>()
        .Transient();
});

这个方案的好处是扩展性极强——以后新增IFoo的实现类,完全不用额外配置,自动就能拿到独立的Bar实例。

方案3:用工厂模式手动生成IBar实例

如果上面的容器配置方式不符合你的需求,也可以换个思路,在Foo类里通过工厂来创建Bar,彻底绕开容器的生命周期限制。不过这个方法需要修改Foo的代码:

首先定义一个简单的工厂接口和实现:

public interface IBarFactory
{
    IBar Create();
}

public class BarFactory : IBarFactory
{
    public IBar Create() => new Bar();
}

然后修改Foo的构造函数,依赖工厂而不是直接依赖IBar:

public class Foo1 : IFoo {
    public IBar bar { get; set; }
    public Foo1(IBarFactory barFactory) { this.bar = barFactory.Create(); }
}

public class Foo2 : IFoo {
    public IBar bar { get; set; }
    public Foo2(IBarFactory barFactory) { this.bar = barFactory.Create(); }
}

最后在容器里注册工厂:

var container = new Container(_ => {
    _.Scan(x => {
        x.TheCallingAssembly();
        x.AddAllTypesOf<IFoo>();
    });
    _.For<IBar>().Use<Bar>(); // 全局配置保留
    _.For<IBarFactory>().Use<BarFactory>(); // 注册工厂
});

这样每个Foo实例都会通过工厂创建全新的Bar,完全不受全局IBar生命周期的影响,同时其他模块的IBar使用也不会被干扰。

验证效果

不管用哪种方案,运行你的测试代码:

var foos = container.GetAllInstances<IFoo>();
if (foos.ElementAt(0).bar.id == foos.ElementAt(1).bar.id)
    throw new Exception("Bar must be a different instance");

现在都不会再抛出异常了,每个Foo的bar都是独立的Bar实例。

内容的提问来源于stack exchange,提问作者Daryl Van Sittert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:29:46