質問

Autofac has modules, Windsor has Installers and StructureMap Registries ... with Simple Injector how can I pack configuration logic into reusable classes?

I have tried:

public interface IModule { }

public class FooModule : IModule
{
    public FooModule(SimpleInjector.Container container)
    {
        container.RegisterSingleton<IBar, Bar>();
        container.RegisterSingleton<IFoo, Foo>();
    }
}

And I use it in the Composition Root:

public static void Main(string[] args)
{
    var container = new SimpleInjector.Container();
    container.RegisterCollection<IModule>(new FooModule(container));
    ...
}

However, FooModule depends on container and maybe in not a good practice... see http://code.google.com/p/autofac/wiki/BestPractices:

If components have a dependency on the container, look at how they're using the container to retrieve services, and add those services to the component's (dependency injected) constructor arguments instead.

役に立ちましたか?

解決

A 'module' feature is deliberately left out of the Simple Injector core library, but there is a SimpleInjector.Packaging NuGet package that allows you to do this. 'Package' is the term Simple Injector uses. This library however, is nothing more than one IPackage interface and two extension methods. You can achieve the same by writing code like this:

A package:

public static class BootstrapperPackage
{
    public static void RegisterServices(Container container)
    {
        container.Register<IBar, Bar>(Lifestyle.Scoped);
        container.Register<IFoo, Foo>(Lifestyle.Singleton);            
    }
}

In your composition root:

public static void Main(string[] args)
{
    var container = new SimpleInjector.Container();

    BootstrapperPackage.RegisterServices(container);

    ...
}

The difference with the SimpleInjector.Packaging NuGet package is that this package defines an interface for you, and allows you to dynamically load multiple packages in one single line:

public class BusinessLayerPackage : IPackage
{
    public void RegisterServices(Container container)
    {
        container.Register<IBar, Bar>(Lifestyle.Scoped);
        container.Register<IFoo, Foo>(Lifestyle.Singleton);            
    }
}

public static void Main(string[] args)
{
    var container = new SimpleInjector.Container();

    container.RegisterPackages(AppDomain.CurrentDomain.GetAssemblies());
}

However, if you don't really need dynamic loading, using static methods (as shown above) is preferred, because it has the following advantages:

  • Makes loading modules very explicit and discoverable.
  • Makes it easy to select which modules to load and which not.
  • Makes it easy to pass along extra values to the RegisterServices methods, such as configuration values that such module requires. This prevents the module from taking a hard dependency on the configuration system.

For more information, please read this.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top