Search code examples
c#database-connectioncastle-windsortyped-factory-facility

Component-specific Castle Windsor typed factory


I have an application that uses several different database connections. I would like to use Castle Windsor's typed factory support to inject a factory that returns instances of IDbConnection into my repositories and other components.

Here's how the interface for my typed factory looks like:

public interface IConnectionFactory
{
    IDbConnection CreateConnection();
}

And here's a sample repository:

public class AccountRepository
{
     private readonly IConnectionFactory connectionFactory;

     public AccountRepository(IConnectionFactory connectionFactory)
     {
         this.connectionFactory = connectionFactory;
     }

     public Account FindAccountById(int id)
     {
         using (var connection = connectionFactory.CreateConnection())
         {
             // TODO use the connection here
         }
     }
}

And an excerpt of my component registration:

// ...

container.Register(Component.For<IDbConnection>()
    .ImplementedBy<NpgsqlConnection>()
    .LifestyleTransient());

container.Register(Component.For<IConnectionFactory>()
     .AsFactory());

// ...

All my IDbConnections are implemented using the same type (NpgsqlConnection), but I have several different connection strings I need to use. Ideally, I would like to setup Windsor to set the connection string on the IDbConnection (or pass it into the connection constructor) for me depending on the component that has IConnectionFactory as a dependency.

For example:

  • Say I have two repositories, AccountRepository and ItemRepository, that take IConnectionFactory as a dependency in their constructors.
  • Say I also have two connection strings named foo and bar.
  • When AccountRepository calls IConnectionFactory.CreateConnection(), I want it to return an IDbConnection using connection string foo.
  • However, when a ItemRepository calls IConnectionFactory.CreateConnection(), I want it to return an IDbConnection using connection string bar.

Is this possible with Castle Windsor?

I've researched this topic but haven't find any solution that fits my exact scenario. Ideally, I would like to keep my repositories ignorant of the exact connection string to use, i.e. I do not want to change my connection factory to:

public interface IConnectionFactory
{
    IDbConnection CreateConnection(string connectionStringName);
}

I've also read all the documentation and articles I could find on ISubDependencyResolver and ITypedFactoryComponentSelector but I'm not sure if they are applicable in this scenario or how to piece everything together.

By the way, I am using Castle Windsor 3.1 and .NET 4.0.


Solution

  • Maybe use a real Factory, and not a typed one:

    public ConnectionAFactory : IConnectionFactory
    {
         public ConnectionAFactory()
         {
              this.connectionString = "foo";
         }
    }
    

    And register it in windsor with the correct Repository:

    Component.For<AccountRepository>()
        .DependsOn(
            ServiceOverride.ForKey<IConnectionFactory>().Eq(typeof(ConnectionAFactory)));