如何将配置参数传递给SimpleInjector包装?

dan*_*wig 4 settings configuration packaging inversion-of-control simple-injector

所以SimpleInjector现在有一个包装nuget,您可以用它来隔离根组合的不同方面.

假设我在库中有一个可配置的组合根,它可以被应用程序中的多个项目重用.例如,在Azure解决方案中,我可能有一个Web角色和一个Worker角色,它们大部分共享大量相同的依赖项,但具有略微不同的配置选项,具体取决于使用者.当我RootCompositionSettings编写根时,我可以传入一个普通的旧对象,该对象具有告诉SimpleInjector如何注册依赖项的属性.

但是,我不确定如何(或者如果)我可以将这些设置传递给IPackage实例.是否可以将自定义设置传递给SimpleInjector包,如果是,如何?

我看到注册包的标准做法是调用

container.RegisterPackages(); // scans all loaded assemblies for IPackage
// or
container.RegisterPackages(IEnumerable<Assembly>) // specific assemblies only
Run Code Online (Sandbox Code Playgroud)

...那么我们如何将参数传递给包装实例?有没有办法通过容器做到这一点?

Ste*_*ven 5

这里的技巧是将容器上的信息传递给包.您可以使用容器的Items字典来完成此操作,这很像ASP.NET的HttpContext.Items集合.这可以按如下方式完成:

using SimpleInjector.Advanced;

container.SetItem(typeof(RootCompositionSettings), settings);

container.RegisterPackages();
Run Code Online (Sandbox Code Playgroud)

现在,在您的包中,您可以执行以下操作:

var settings =(RootCompositionSettings)container.GetItem(typeof(RootCompositionSettings));

请注意:

  • SetItem并且GetItem是位于SimpleInjector.Advanced命名空间中的扩展方法.这些方法允许您访问(内部)Items字典.
  • 你可以传入任何你喜欢的密钥.typeof(RootCompositionSettings)在这种情况下,传入方便,但不是必需的.

如果您需要在更多地方调用设置,那么创建一个允许您访问设置实例的更具体的扩展方法可能会很有用,但这取决于您.

另一种选择是根本不使用IPackage接口和SimpleInjector.Packaging库.在大多数情况下,它并没有真正添加任何内容,您只需在程序集中定义一个与程序包相同的公共静态方法.例如:

public static class BusinessLayerBootstrapper
{
    public static void Bootstrap(Container container, ScopedLifestyle scopedLifestyle,
        RootCompositionSettings settings)
    {
        // Here the same logic as what you would write in your package.
    }
}
Run Code Online (Sandbox Code Playgroud)

大多数应用程序不是动态的,您需要动态加载程序集,并且启动项目通常具有对所有其他程序集的硬引用.在这种情况下,简单地调用静态方法是完全理智的.

即使你有动态加载程序集的要求并允许它们在容器中注册它们的东西,构建自己的IPackage抽象也是非常简单的:

// Your own IPackage interface
public interface IPackage
{
    void RegisterServices(Container container, RootCompositionSettings settings);
}

// Your own extension method
public static void RegisterPackages(this Container container, 
    RootCompositionSettings settings)
{
    var packages =
        from assembly in AppDomain.CurrentDomain.GetAssemblies()
        from type in assembly.GetExportedTypes()
        where typeof(IPackage).IsAssignableFrom(type)
        where !type.IsAbstract
        select (IPackage)Activator.CreateInstance(type);

    packages.ToList().ForEach(p => p.RegisterServices(container, settings));
}
Run Code Online (Sandbox Code Playgroud)

实际上,除了一些额外的验证和过滤掉动态程序集之外,SimpleInjector.Packaging项目并不比这更多.