Castle Windsor Resolve at run time
Asked Answered
G

1

8

I have been trying to fix this issue for quite a while and I am still none the wiser. I have got the following method:

public IResult Parse(string[] args)
{
    var argumentOption = new ArgumentOption(_dataModelBinder);
    var boundArgumentOption = argumentOption.Bind(args);

    var bindingResults = boundArgumentOption.Validate(_argumentOptionValidator);

    // AREA OF INTEREST
    if (bindingResults.Any())
    {
        return new ErrorResult();
    }

    return new CreateReportResult(
        _resultActioner
        , boundArgumentOption.OutputFilePath
        , boundArgumentOption.PatientId
        , "database");
}

The code I'm having trouble with involves the return values which I'm newing up, which ideally I'd like to leave to Castle Windsor to deal with. So, what I then did was to create an Abstract factory:

public interface IResultFactory
{
    IResult Create(int numOfErrors);
} 

public class ResultFactory : IResultFactory
{
    private readonly IWindsorContainer _container;

    public ResultFactory(IWindsorContainer container)
    {
        _container = container;
    }

    public IResult Create(int numOfErrors)
    {
        if (numOfErrors > 0)
        {
            return _container.Resolve<IResult>("ErrorResult");
        }

        return _container.Resolve<IResult>("CreateReportResult");
    }
}

and my Parse method now becomes:

public IResult Parse(string[] args)
{
    var argumentOption = new ArgumentOption(_dataModelBinder);
    var boundArgumentOption = argumentOption.Bind(args);

    var bindingResults = boundArgumentOption.Validate(_argumentOptionValidator);

    IResult result = _factory.Create(bindingResults.Count());

    return result;
}

What I'm having a great deal of problem with is how to do the registration and dynamically pass in the parameters because the constructor for CreateReportResult is:

public CreateReportResult(IResultActioner resultActioner, Uri filePath, string patientId, string dataSource)

So the question is how do I set up my registration code in my WindsorContainer installer and how do I then pass in the required parameters? I am using Castle Windsor 3.2.

Here is the code I have in my registration:

container.Register(
  Component
    .For<IResult>()
    .ImplementedBy<ErrorResult>()
    .Named("ErrorResult")
    .LifeStyle.Transient
    , Component.For<IResultFactory>()
    .AsFactory()
);

container.Register(
  Component
    .For<IResult>()
    .ImplementedBy<CreateReportResult>()
    .Named("CreateReportResult")
    .LifeStyle.Transient
    , Component.For<IResultFactory>()
    .AsFactory()
);
Garica answered 8/5, 2013 at 9:25 Comment(0)
C
5

I think you should be looking at the typed factory facility in windsor. The paramaters are passed along, as long as they have the same name in the implementation as in the registration.

Capful answered 8/5, 2013 at 9:41 Comment(5)
Hi Martin, I did come across the typed factory but I can't figure out how to use it for my purposes because I don't quite know how to do the registration properly. I've updated my OP to show what I've got.Garica
The trick is that the typed factory does not by default require an implementation. In order to resolve to your component by the int amountoferrors parameter you need to implement the ITypedFactoryComponentSelector as described in the link above. In there you can return the name of the component you would like to resolve to based on the methodinfo and parameters passed in. If you need more parameters passed along in order to instantiate an implementation, then the signature for the factory needs to change accordingly. (all parameters need to be passed to the factory).Capful
Thanks for the explanation Martin. For anyone interested in how I went about this, I've blogged about this davidsiew.wordpress.com/2013/05/08/….Garica
Thanks for the mention on your blog David.Capful
The typed factory facility will only pass along parameters to the immediately requested implementation class. It won't automatically pass them further down the dependency chain. You need to use dynamic parameters to accomplish that.Formate

© 2022 - 2024 — McMap. All rights reserved.