tags:

views:

243

answers:

1

I have a base class of Repository<T>. In a particular project I have several implemetations of this base class. e.g.

PersonRepository : Repository<T>
EmployerRepository : Repository<T>

Right now, I am register each of these repositories in a StructureMap ServiceRegistry class. like this:

ForRequestedType<Repository<Person>>()
  .TheDefaultIsConcreteType<PersonRepository>();
ForRequestedType<Repository<Employer>>()
  .TheDefaultIsConcreteType<EmployerRepository>();

This sucks, because every time I add a repository, I have to remember to register it. It's one more step.

Is there a way that I could search the project/assembly where PersonRepository is located and register everything that inherits from Repository<T>?

+2  A: 

EDIT: I've just downloaded newest build of StructureMap from project's CI server. What you need is now included, and there is no need to use custom convention:

public class RepositoryRegistry : Registry
{
    public RepositoryRegistry()
    {
        Scan(assemblyScanner =>
             {
                 assemblyScanner.AssemblyContainingType<PersonRepository>();
                 assemblyScanner.AddAllTypesOf(typeof (IRepository<>));
                 assemblyScanner.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
             });
    }
}

This is my initial solution:

That's a good starting point, but probably needs to be refined:

public class RepositoryRegistry : Registry
{
    public RepositoryRegistry()
    {
        Scan(assemblyScanner =>
             {
                 assemblyScanner.AssemblyContainingType<PersonRepository>();
                 assemblyScanner.AddAllTypesOf(typeof (IRepository<>));
                 assemblyScanner.With<RepositoryConvention>();
             });
    }
}

public class RepositoryConvention : ITypeScanner
{
    public void Process(Type type, PluginGraph graph)
    {
        var selectedInterface =
            (from @interface in type.GetInterfaces()
            where @interface.IsGenericType &&
                  @interface.GetGenericTypeDefinition()
                      .IsAssignableFrom(typeof (IRepository<>))
            select @interface).SingleOrDefault();

        if(selectedInterface != null)
            graph.Configure(registry =>
                 registry.ForRequestedType(selectedInterface)
                    .TheDefaultIsConcreteType(type)
             );
    }
}
maciejkow
Cool! Thanks! I'll give this a try in a couple weeks when I get back from vacation.
Lance Fisher