简单注入器 DI 容器嵌套范围

问题描述 投票:0回答:1

有一个控制台应用程序。有3项服务:

public class SingletonService
{
    public SingletonService()
    {
        Console.WriteLine("SingletonService constructor");
    }
}

public class AppScopeService
{
    public AppScopeService(SingletonService singletonService)
    {
        Console.WriteLine("AppScopeService constructor");
    }
}

public class InnerScopeService
{
    public InnerScopeService(SingletonService singletonService, AppScopeService appScopeService)
    {
        Console.WriteLine("InnerScopeService constructor");
    }
}

我使用 Simple Injector DI 容器来创建服务:

public class ScopeExperiment
{
    public ScopeExperiment()
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = ScopedLifestyle.Flowing;
        container.Register<SingletonService>(Lifestyle.Singleton);
        container.Register<AppScopeService>(Lifestyle.Scoped);
        container.Register<InnerScopeService>(Lifestyle.Scoped);

        
        using (var appScope = new Scope(container))
        {
            Console.WriteLine("<------app scope----->");
            var app = appScope.GetInstance<AppScopeService>();

            using (var innerScope = new Scope(container))
            {
                Console.WriteLine("<------inner scope----->");
                var innerService = innerScope.GetInstance<InnerScopeService>();
            }

            using (var innerScope = new Scope(container))
            {
                Console.WriteLine("<------inner scope 2----->");
                var innerService = innerScope.GetInstance<InnerScopeService>();
            }
        }
    }
}

运行:程序>new ScopeExperiment();

控制台结果:

<------app scope----->

SingletonService constructor

AppScopeService constructor

InnerScopeService constructor

<------inner scope----->

AppScopeService constructor

InnerScopeService constructor

<------inner scope 2----->

AppScopeService constructor

InnerScopeService constructor

预期结果:

<------app scope----->

SingletonService constructor

AppScopeService constructor

InnerScopeService constructor

<------inner scope----->

InnerScopeService constructor

<------inner scope 2----->

InnerScopeService constructor

“InnerScopeService”在构造函数中注入“AppScopeService”。问题是每次创建“InnerScopeService”时都会创建“AppScopeService”。所需的行为是每个“appScope”仅创建一次“AppScopeService”。

  1. 有什么方法可以向 DI 容器解释我想从外部作用域(appScope)获取依赖关系。
  2. simpleInjector DI 容器支持嵌套作用域吗?
c# dependency-injection scope simple-injector
1个回答
1
投票

嵌套作用域不是开箱即用的支持功能,但可以例如使用下面的代码来实现。

注意: 您需要为

AppScopeService
添加抽象,如下面的代码所示:

有3项服务:

public class SingletonService
{
    public SingletonService()
    {
        Console.WriteLine("SingletonService constructor");
    }
}

public interface IAppScopeService { }

// NOTE: AppScopeService now implements IAppScopeService
public class AppScopeService : IAppScopeService
{
    public AppScopeService(SingletonService singletonService)
    {
        Console.WriteLine("AppScopeService constructor");
    }
}

public class InnerScopeService
{
    // NOTE: InnerScopeService now depends on IAppScopeService
    public InnerScopeService(
        SingletonService singletonService,
        IAppScopeService appScopeService)
    {
        Console.WriteLine("InnerScopeService constructor");
    }
}

创建服务:

public ScopeExperiment()
{
    var container = new Container();
    container.Options.EnableAutoVerification = false;
    container.Options.DefaultScopedLifestyle = ScopedLifestyle.Flowing;
    container.Register<SingletonService>(Lifestyle.Singleton);
    container.Register<InnerScopeService>(Lifestyle.Scoped);

    container.Register<AppScopeService>(Lifestyle.Scoped);
    container.Register<IAppScopeService>(() =>
    {
        var scope = container.GetInstance<Scope>();
        return (scope.GetItem("Parent") as Scope ?? scope)
            .GetInstance<AppScopeService>();
    });

    using (var appScope = new Scope(container))
    {
        Console.WriteLine("<------app scope----->");
        var app = appScope.GetInstance<AppScopeService>();

        using (var innerScope = new Scope(container))
        {
            innerScope.SetItem("Parent", appScope);
            Console.WriteLine("<------inner scope----->");
            var innerService = innerScope.GetInstance<InnerScopeService>();
        }

        using (var innerScope = new Scope(container))
        {
            innerScope.SetItem("Parent", appScope);
            Console.WriteLine("<------inner scope 2----->");
            var innerService = innerScope.GetInstance<InnerScopeService>();
        }
    }
}

控制台结果:

<------app scope----->
SingletonService constructor
AppScopeService constructor
<------inner scope----->
InnerScopeService constructor
<------inner scope 2----->
InnerScopeService constructor
© www.soinside.com 2019 - 2024. All rights reserved.