views:

259

answers:

2

In my registry I have

Scan(scanner =>
         {
             scanner.AssemblyContainingType<EmailValidation>();
             scanner.ConnectImplementationsToTypesClosing(typeof(IValidation<>));
         });

What am I supposed to do to define these all as Singletons?

Also as an aside to this question, is there any reason to not define everything that is stateless as a singleton object that's registered in StructureMap?

+1  A: 

The assembly scanner method ConnectImplementationsToTypesClosing uses a IRegistrationConvention to get the job done. To do this I copied and updated the StructureMap generic connection scanner to also take a scope. Next I created a handy assembly scanner extension method to use as syntactic sugar to wire it up.

    public class GenericConnectionScannerWithScope : IRegistrationConvention
{
    private readonly Type _openType;
    private readonly InstanceScope _instanceScope;

    public GenericConnectionScannerWithScope(Type openType, InstanceScope instanceScope)
    {
        _openType = openType;
        _instanceScope = instanceScope;

        if (!_openType.IsOpenGeneric())
        {
            throw new ApplicationException("This scanning convention can only be used with open generic types");
        }
    }

    public void Process(Type type, Registry registry)
    {
        Type interfaceType = type.FindInterfaceThatCloses(_openType);
        if (interfaceType != null)
        {
            registry.For(interfaceType).LifecycleIs(_instanceScope).Add(type);
        }
    }
}

public static class StructureMapConfigurationExtensions
{
    public static void ConnectImplementationsToSingletonTypesClosing(this IAssemblyScanner assemblyScanner, Type openGenericType)
    {
        assemblyScanner.With(new GenericConnectionScannerWithScope(openGenericType, InstanceScope.Singleton));
    }
}

Here is the appropriate setup code.

Scan(scanner =>
     {
         scanner.ConnectImplementationsToSingletonTypesClosing(typeof(IValidation<>));
     });

Hope this helps.

KevM
This definitely looks like a solution, it's dumb this needs to be done for something so simple however this looks very similar to a post I saw on the SM group earlier that I think Jeremy might be adding adding a way to specify that without needing to implement your own convention in 2.5.5 and now seeing your post it makes alot of sense what it was about.
Chris Marisic
Sorry didn't see that post. I work with Jeremy. To create my solution I just grabbed the StructureMap source and figured out how he was doing this and adapted it per your request. It might benefit from some more flexibility or better integration with the SM configuration DSL but this will get you going for now. Enjoy.
KevM
+3  A: 

Kevin's answer is correct for versions 2.5.4 and older. In the current StructureMap trunk (and when 2.5.5+ is released), you can now do:

Scan(scanner =>
{
   scanner.AssemblyContainingType<EmailValidation>();
   scanner.ConnectImplementationsToTypesClosing(typeof(IValidation<>))
          .OnAddedPluginTypes(t => t.Singleton());
});
Joshua Flanagan
very nice added featured, can't wait for 2.5.5!
Chris Marisic