Define filter for DecorateAllWith() method in structure-map 3

516 views Asked by At

I used following statement to decorate all my ICommandHandlers<> with Decorator1<>:

ObjectFactory.Configure(x =>
{
   x.For(typeof(ICommandHandler<>)).DecorateAllWith(typeof(Decorator1<>));
});

But because Decorator1<> implements ICommandHandlers<>, the Decorator1<> class decorates itself too.

So, the problem is that the Decorator1 registers inadvertently, when I register all the ICommandHandler<>'s. How can I filter DecorateWithAll()to decorate all ICommandHandler<>, except Decorator1<>?

1

There are 1 answers

1
qujck On BEST ANSWER

ObjectFactory is obsolete.

You can exclude Decorator1<> from being registered as a vanilla ICommandHandler<> with code like this:

var container = new Container(config =>
{
    config.Scan(scanner =>
    {
        scanner.AssemblyContainingType(typeof(ICommandHandler<>));
        scanner.Exclude(t => t == typeof(Decorator1<>));
        scanner.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
    });
    config.For(typeof(ICommandHandler<>)).DecorateAllWith(typeof(Decorator1<>));
});

UPDATE

For multiple modules you can use The Registry DSL to compose a portion of your application

using StructureMap;
using StructureMap.Configuration.DSL;

public class CommandHandlerRegistry : Registry
{
    public CommandHandlerRegistry()
    {
        Scan(scanner =>
        {
            scanner.AssemblyContainingType(typeof(ICommandHandler<>));
            scanner.Exclude(t => t == typeof(Decorator1<>));
            scanner.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
        });
        For(typeof(ICommandHandler<>)).DecorateAllWith(typeof(Decorator1<>));
    }
}

Only the Composition Root needs to be aware of all the Registry implementations.

 var container = new Container(config =>
{
    config.AddRegistry<CommandHandlerRegistry>();
});

You even have the option of finding all Registry instances at runtime (you still need to ensure all the required assemblies are loaded)

var container = new Container(config =>
{
    var registries = (
        from assembly in AppDomain.CurrentDomain.GetAssemblies()
        from type in assembly.DefinedTypes
        where typeof(Registry).IsAssignableFrom(type)
        where !type.IsAbstract
        where !type.Namespace.StartsWith("StructureMap")
        select Activator.CreateInstance(type))
        .Cast<Registry>();

    foreach (var registry in registries)
    {
        config.AddRegistry(registry);
    }
});