3

I have a Service class that connects to a database and pulls data. A new requirement is that I connect to a second (or N) database that has the same schema, and pull the data the same way. (Each DB has different records, being setup regionally).

I'd like to reuse the Service class, and just pass in the connection string to the service. (The connection string is currently in App.config).

So, I'd like to register an instance of my service class for each database to which I'd like to connect, passing the connection string to the constructor.

Is this possible in Castle Windsor?

My best option right now is:

public class ServiceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        foreach (var connection in Properties.Settings.Default.ServicedDBs)
        {
            container.Register(
                Component.For<IService>()
                .Named(connection)
                .UsingFactoryMethod(() => new Service(
                    container.Resolve<ILog>(),
                    connection)));
        }
    }
}
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
pomeroy
  • 1,377
  • 1
  • 12
  • 21
  • BTW - I see you inject the logger in the constructor. In my opinion this is a weak dependency and best fits to be injected via property and not constructor. – Gilad Green Oct 04 '16 at 17:57

1 Answers1

4

It is possible. Implement your service to have a constructor that requests the connection string:

public interface IService { }
public class Service : IService
{
    public Service(string connectionString)
    {
        ConnectionString = connectionString;
    }
    public string ConnectionString { get; set; }
}

And then when registering the component use the .DependsOn to specify the dependencies:

public class ServiceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        foreach (var connection in Properties.Settings.Default.ServicedDBs)
        {
           container.Register(
               Component.For<IService>()
                        .ImplementedBy<Service>()
                        .DependsOn(Dependency.OnValue("connectionString", connection)
                        .Named(connection)));
        }
    }
}

You can also have it as a property and use Property Injection to set it but in my opinion this is a dependency fitting for the constructor. For more about it read: Dependency injection through constructors or property setters?


There was once a link to SO Documentation on the .DependsOn topic, but that was not part of the last version of the documentation that was generally visible. The reference has been removed as part of the cleanup process.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Gilad Green
  • 36,708
  • 7
  • 61
  • 95