是否有允许使用“子作用域”的 DI 容器

本文关键字:子作用域 DI 容器 作用域 许使用 是否 | 更新日期: 2023-09-27 18:22:20

是否有任何具有"子作用域"概念的 .NET DI 容器?

像这样:

var container = AppConfiguredContainer();
using(var childContainer = container.GetChild())
{
  childContainer.Register<IFoo>(typeof(Foo));
  // do stuff with childContainer
}

关键是在子容器中完成的任何服务配置都不会影响应用程序范围的配置。

是否有允许使用“子作用域”的 DI 容器

下面是

与 NInject 绑定的子作用域的示例:

var k = new StandardKernel();
k.Bind<Application>().ToSelf().InSingletonScope().DefinesNamedScope("Application");
k.Bind<UserRepository>().ToSelf().InNamedScope("Application");
const string userScopeName = "User";
k.Bind<UserScope>().ToSelf().DefinesNamedScope(userScopeName);
k.Bind<User>().ToSelf().InNamedScope(userScopeName);
k.Bind<User.ChatService>().ToSelf().InNamedScope(userScopeName);
k.Bind<User.SheetService>().ToSelf().InNamedScope(userScopeName);
const string nestedScopeName = "UserSheet";
k.Bind<User.Sheet>().ToSelf().DefinesNamedScope(nestedScopeName);
k.Bind<User.Sheet.SheetInfo>().ToSelf().InNamedScope(nestedScopeName);
k.Bind<User.Sheet.SheetCalculator>().ToSelf().InNamedScope(nestedScopeName);

您需要引用Ninject.Extensions.NamedScope并使用Ninject.Extensions.ContextPreservatioon Ninject.Extensions.Factory

每个Repository可以加载多个用户,每个用户在"子作用域"中都有多个Sheets

public class UserRepository
{
    Func<UserScope> _factory;
    [Inject]
    public UserRepository(Func<UserScope> factory)
    {
        _factory = factory;
    }
    public UserScope LoadUser()
    {
        return _factory(); // scopes preserved
    }
}

public class User
{
    Func<Sheet> _sheetFactory; // multiple instances inside User scope
    public UserRepository Repository { get; } // same instance for app
    [Inject]
    public User(Func<Sheet> sheetFactory, UserRepository repository)
    {
        Repository = repository;
        _sheetFactory = sheetFactory;
    }
    public Sheet MakeSheet()
    {
        return _sheetFactory();
    }
}

将类用作User容器非常重要UserScope因为否则无法从其依赖项内部解析相同的User实例:

public class UserScope : IDisposable
{
    [Inject]
    public UserScope(User user, IResolutionRoot resolver)
    {
        User = user;
        Resolver = resolver;
    }
    public User User { get; }
    public IResolutionRoot Resolver { get; } // you can use this to resolve anything from inside **this** user scope
}

然后,您可以加载用户,例如:

var app = k.Get<Application>(); // singleton
var u1 = app.Repository.LoadUser();
var u2 = app.Repository.LoadUser();

它们中的每一个都将具有相同的ApplicationRepository实例,但不同的ChatServiceSheetService实例。