Isn't it annoying to have to register all your repository implementations by hand?  When you get to a certain number of them, it becomes quite a task.  If you want to register them for multiple interfaces, it gets even worse.

When using Windsor as your inversion of control container, separating your repository registrations into a facility is a good start.  In general though, all our repositories follow a simple pattern and should be easily registerable automatically following an algorithm.

Domain driven design tells us that the repository interfaces are a part of the domain but the implementations are not.  Therefore, we usually have two assemblies that are important.

This is a typical project layout:

Our facility needs to allow us to configure what assemblies it searches for types and the base type of the repository. 

Specification

Here is a simple test describing the desired behavior:

    [TestFixture]
    public class RepositoryRegistrationFacilityTestFixture
    {
        [Test]
        public void ShouldRegisterCustomerRepository()
        {
            var kernel = new Castle.MicroKernel.DefaultKernel();



            var facility = new RepositoryRegistrationFacility(typeof (IRepository<>), typeof (Customer).Assembly);

            facility.Init(kernel,
            new Castle.Core.Configuration.MutableConfiguration("facility-config"));



            kernel.Resolve<ICustomerRepository>().ShouldBeInstanceOfType(typeof (CustomerRepository));             kernel.Resolve<IRepository<Customer>>().ShouldBeInstanceOfType(typeof (CustomerRepository));
        }



        protected interface IRepository<T>         {         }         protected interface ICustomerRepository : IRepository<Customer>         {            }         protected class CustomerRepository : ICustomerRepository         {         }         protected class Customer         {         }     }

Implementation

    public class RepositoryRegistrationFacility : AbstractFacility
    {
        private readonly Assembly[] assemblies;
        private readonly Type genericRepositoryType;

        public RepositoryRegistrationFacility(Type genericRepositoryType, params Assembly[] assemblies)
        {
            this.assemblies = assemblies;
            this.genericRepositoryType = genericRepositoryType;
        }

        protected override void Init()
        {
            Predicate<Type> isGenericRepositoryInterface =
                type =>
                type.GetInterfaces().Contains(
                    x => x.IsGenericType && x.GetGenericTypeDefinition().IsAssignableFrom(genericRepositoryType));

            IEnumerable<Type> types =
                assemblies.Aggregate(Enumerable.Empty<Type>(), (accumulator, assembly) => accumulator.Concat(assembly.GetTypes()));

            IEnumerable<Type> repositoryInterfaces = types.Where(
                type => type.IsInterface && !type.IsGenericTypeDefinition && isGenericRepositoryInterface(type));

            repositoryInterfaces
                .ForEach(interfaceType =>
                             {
                                 Type implementor =
                                     types.FirstOrDefault(type => interfaceType.IsAssignableFrom(type) && !type.IsAbstract);
                                 if (implementor == null) return;

                                 IEnumerable<Type> genericRepositoryInterfaceTypes = implementor.GetInterfaces().Where(
                                     x =>
                                     x.IsGenericType &&
                                     x.GetGenericTypeDefinition().IsAssignableFrom(genericRepositoryType));

                                 Kernel.Register(
                                     Component.For(interfaceType).ImplementedBy(implementor).Forward(
                                         genericRepositoryInterfaceTypes));
                             });
        }
    }

Now in fluent configuration you can just do this:

container.AddFacility("persistent-repository-facility", new RepositoryRegistrationFacility(typeof(IRepository<>), typeof(IRepository<>).Assembly, typeof(SomethingRepository).Assembly));

I have not tested the binsor registration, but you should be able to do something like this to register it using binsor:

facility RepositoryRegistrationFacility:
    genericRepositoryType: IRepository
    assemblies: array(System.Reflection.Assembly, IRepository.Assembly, SomethingRepository.Assembly)

I hope this is useful.

kick it on DotNetKicks.com