Use a registered component in a Castle container to provide a dependency for another component

I have a Castle Windsor container registration class like this:

public class WindsorInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {           
        container.Register(Component.For<IConfigProvider>()
            .ImplementedBy<ConfigProvider>()
            .LifeStyle.Singleton);

        container.Register(Component.For<IDbRepository>()
            .ImplementedBy<DbRepository>()
            .LifeStyle.Singleton                
            .DependsOn(Dependency.OnValue(
                "connectionString", 
                // -- Somehow call GetConfig() on the IConfigProvider --
        )));                
    }
}

      

DbRepository requires a connection string to be passed when constructing the object. However, this connection string is actually provided by IConfigProvider.

Is it possible to force Castle Windsor to somehow resolve the IConfigProvider at this point and call the GetConfig method?

Open up to other options if that's not a good idea.

+3


source to share


2 answers


You can use DynamicParameters

to accomplish the following:

container.Register(Component.For<IDbRepository>()
    .ImplementedBy<DbRepository>()
    .LifeStyle.Singleton                
    .DynamicParameters((k,d) => 
    {
        var configProvider = k.Resolve<IConfigProvider>();
        d["connectionString"] = configProvider.GetConfig();
    }
)));      

      

From the documentation:



DynamicParameters works with a delegate that is called at the very beginning of the component resolution pipeline.

In other words, you will get the connection string just before the component is resolved.

+2


source


you might want to test the Windsor lock by typing a factory object.

https://visualstudiomagazine.com/articles/2011/12/01/windsor-beyond-dependency-injection.aspx

Edit:

Here's an example of what you want to do.

http://joseoncode.com/2011/01/09/windsor-isubdependencyresolver-example/

Implement AbstractFacility which will resolve your connection string

    public class DependenciesFromAppSettings : AbstractFacility
{
    protected override void Init()
    {
        var dic = ConfigurationManager
             .AppSettings
             .AllKeys
             .ToDictionary(k => k, k => ConfigurationManager.AppSettings[k]);

        Kernel.Resolver.AddSubResolver(new DependenciesFromAppSettingsResolver(dic));
    }
}

      

ISubDependencyResolver Implementation



    public class DependenciesFromAppSettingsResolver : ISubDependencyResolver
{
    private readonly IDictionary<string, string> webConfig;

    public DependenciesFromAppSettingsResolver(IDictionary<string, string> webConfig)
    {
        /// you can pass in your configprovider object here (or similar)
        this.webConfig = webConfig;
    }

    public bool CanResolve(Castle.MicroKernel.Context.CreationContext context, 
        ISubDependencyResolver contextHandlerResolver, 
        Castle.Core.ComponentModel model, 
        Castle.Core.DependencyModel dependency)
    {
        //make sure your connectionstring has value
    }

    public object Resolve(Castle.MicroKernel.Context.CreationContext context, 
        ISubDependencyResolver contextHandlerResolver, 
        Castle.Core.ComponentModel model, 
        Castle.Core.DependencyModel dependency)
    {
        //resolve your connectionstring here
    }
}

      

Your repositories look like this:

    public class MyRepo 
{
    public MyRepo(string connectionString)
    {

    }

}

      

Your Windsor container castle will look like this (i.e. add an object):

IWindsorContainer container = new WindsorContainer();
        ///Register your ConfigProvider here
        container.AddFacility<DependenciesFromAppSettings>();
        container.Register(Component.For<MyRepo>());

      

Please note that the code is borrowed from the above link.

Hope it helps

0


source







All Articles