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

时间:2014-08-03 18:31:06

标签: configuration settings inversion-of-control packaging simple-injector

So 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

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

1 个答案:

答案 0 :(得分:5)

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

using SimpleInjector.Advanced;

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

container.RegisterPackages();

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

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

请注意:

  • SetItemGetItem是位于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.
    }
}

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

即使您需要动态加载程序集并允许它们在容器中注册它们的东西,但是构建自己的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));
}

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