StructureMap:创建为瞬态(根据请求)不起作用

zac*_*cko 5 c# structuremap dependency-injection ioc-container

我正在尝试解决 IoC 问题,一开始看起来很简单,但结果却很痛苦:-P

我有一个重量级主类,它必须只初始化一次,因此它被标记为单例。然而,该类使用一个必须为每个请求创建一次的子类,因此它被标记为 Transient:

public class MyRegistry : Registry
{
    public MyRegistry()
    {
        For<IMainClass>()
            .Singleton()
            .Use(ctx => new MainClass(() => ctx.GetInstance<ISubClass>()));

        For<ISubClass>()
            .Transient()
            .Use(ctx => CreateNewInstanceOfSubClass());
    }

    private ISubClass CreateNewInstanceOfSubClass()
    {
        return new SubClass();
    }
}

public interface ISubClass
{ }

public class SubClass : ISubClass
{ }

public interface IMainClass
{ }

public class MainClass : IMainClass
{
    private readonly Func<ISubClass> _subClassProvider;

    public MainClass(Func<ISubClass> subClassProvider)
    {
        _subClassProvider = subClassProvider;
    }

    public void DoStuff()
    {
        var requestSpecificInstanceOfSubClass = _subClassProvider();

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我将 lambda 传递给 的构造函数MainClass,该构造函数用于获取 的实例ISubClass。在调试过程中,我绝对可以看到ctx.GetInstance<ISubClass>()每次MainClass需要SubClass实例时都会执行该操作。但令我惊讶的是,SubClass它仅作为单例创建一次,而不是为每个请求创建。

但是,当我container.GetInstance<ISubClass>()直接从代码中的某个位置调用时,行为完全符合预期。SubClass对于每个请求仅创建一次。

我不太确定,但我猜问题来自于传递给 lambda 的上下文对象,它是单例(?)的上下文。但我真的不知道如何在这里获得所需的行为!?

我希望你能帮我解决这个问题。感谢您的回答。

问候,但丁

Nig*_*888 1

看来你需要稍微修改一下设计。为了避免存在强制依赖项,您需要为图的根对象提供比其任何依赖项更短(或相等)的生命周期。

MainClass一种选择是创建一个第三类来管理和之间的交互SubClass

接口

public interface IInteractionManager
{ 
    void DoStuff();
}

public interface IMainClass
{ 
    void DoStuff(ISubclass subclass);
}

public interface ISubClass
{ }
Run Code Online (Sandbox Code Playgroud)

课程

public class InteractionManager : IInteractionManager
{
    private readonly IMainClass mainClass;
    private readonly ISubClass subClass;

    public InteractionManager(
        IMainClass mainClass,
        ISubClass subClass)
    {
        this.mainClass = mainClass;
        this.subClass = subClass;
    }

    public void DoStuff()
    {
        this.mainClass.DoStuff(this.subClass);
    }
}

public class MainClass : IMainClass
{
    public void DoStuff(ISubclass subclass)
    {
        // do something with transient subclass
    }
}

public class SubClass : ISubClass
{ }
Run Code Online (Sandbox Code Playgroud)

登记处

public class MyRegistry : Registry
{
    public MyRegistry()
    {
        // The root of the object graph is transient...
        For<IInteractionManager>()
            .Transient()
            .Use<InteractionManager>();

        // ...therefore, it can have transient dependencies...
        For<ISubClass>()
            .Transient()
            .Use<SubClass>();

        // ...and singleton dependencies.
        For<IMainClass>()
            .Singleton()
            .Use<MainClass>();
    }
}
Run Code Online (Sandbox Code Playgroud)