Windsor Castle: how to pass an argument to the constructor of the "child" element of the type to be resolved

I am trying to find the best (most enjoyable way) to pass an argument to the constructor of the child object of the auto-negotiation parameter.

Why? Because I have a program that performs almost all of its calculations against the same "production" database (defined in the configuration file, so no arguments are required). But now you need to do some work on a “copy” of this database. Therefore, a different connection string is required.

The connection string may be provided to the constructor and is not known at compile time. The problem is that I cannot (or don’t know how) simply access this constructor because it is deeply immersed in the generated elements.

Consider the following (simplified) code snippet:

public class Example
{
    protected readonly IGenerateSomethingFactory Factory;
    public Example(IGenerateSomethingFactory factory)
    {
        Factory = factory;
    }

    public Task DoSomething(string ConnectionString, string a, string b)
    {
        //needs to run somehow using the supplied connection string ...
        return Task.Run(() => Factory.CreateSomething().Execute(a, b));
        //= Task.Run(() => new Something(new UnitOfWork(new DataContext(ConnectionString))).Execute(a, b));
    }

    public Task DoSomething(string a, string b)
    {
        //needs to run using the default connection string (defined in config)
        return Task.Run(() => Factory.CreateSomething().Execute(a, b));
    }
}

The task lies in the first function DoSomething(...).

Note. Castle Windsor installer is as follows:

public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<TypedFactoryFacility>();
        container.Register(Component.For<IGenerateSomethingFactory>().AsFactory());
        container.Register(Classes.FromThisAssembly().InNamespace("x").WithService.FirstInterface());
    }
}

I am looking for a solution that:

  • is thread safe
  • easy to understand (if not easy to think)
  • allows refactoring (so named arguments like "conString")
  • does not require changes in other incompatible codes (i.e. setting public ... properties)
  • does not cause neworcontainer.Resolve<>()

I was looking for selection handlers, but actually did not find what I was looking for.

PS: I am using Castle Windsor 3.3.0

PPS: , , , ... , .

+4
1

, , , , factory CreateSomething :

public interface IGenerateSomethingFactory
{
    ISomething CreateSomething(string connectionString);
}

ISomething:

public class Something : ISomething
{
    public Something(string connectionString)
    {
    }
}

, CreateSomething Something . .

DoSomething:

public Task DoSomething(string ConnectionString, string a, string b)
{
    return Task.Run(() => Factory.CreateSomething(ConnectionString).Execute(a, b));
}

, , , . , :

  • IGenerateSomethingFactory.Create(string constring)
    • Something.ctor(IUnitOfWork uow)
      • UnitOfWork.ctor(IDataContext context)
        • DataContext.ctor(string constring)

Create DataContext.

, . ( ). , , factory , .

, :

public class DefaultDependencyResolverInheritContext : DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(CreationContext current, Type parameterType)
    {
        if (parameterType.ContainsGenericParameters)
        {
            return current;
        }

        return new CreationContext(parameterType, current, true);
    }
}

:

var kernel = new DefaultKernel(
                 new DefaultDependencyResolverInheritContext(), 
                 new NotSupportedProxyFactory());
var container = new WindsorContainer(kernel, new DefaultComponentInstaller());

. , Create, constring . , , , ! "ambient" ( ), / .

, .

+2

All Articles