Resolving dynamically base on name convention in Castle Windsor

时光毁灭记忆、已成空白 提交于 2019-12-21 20:23:07

问题


I have a seemingly simple use case. There is a ICsvReader component. Let's name it simply Reader here. We load a known set of CSV files and some of them have headers and some don't. Currently there are multiple readers: Reader_Skips1Row, Reader_Skips2Rows etc.

Is there a way to register only one component and have Windsor look at the component key, strip the "_Skips..." part and resolve the required component with relevant properties set?

I have tried subresolver and facility with no luck.

EDIT

Yes there is only one implementation but it is used as a dependency and configured to be resolved by name. The reader is configured in code

Component.For<ICsvReader>()
         .ImplementedBy<CommaSeparetedCsvReader>()
         .DependsOn(new { SkipHeader = true, HeaderRowsToSkip = 2 } )
         .Named("CommaSeparetedCsvReader_Skips2Rows")
         .Lifestyle.Transient

Component.For<ICsvReader>()
         .ImplementedBy<CommaSeparetedCsvReader>()
         .DependsOn(new { SkipHeader = true, HeaderRowsToSkip = 1 } )
         .Named("CommaSeparetedCsvReader_Skips1Row")
         .Lifestyle.Transient

Component.For<ICsvReader>()
         .ImplementedBy<CommaSeparetedCsvReader>()
         .Named("CommaSeparetedCsvReader")
         .Lifestyle.Transient

These are used as dependency in a processor class. It is configured in XML, so that in can be manipulated at runtime

<component id="Processor 
   type="Processor">
   <parameters>
      <reader>CommaSeparetedCsvReader_Skips2Rows</reader>
   </parameters>
</component>

Ideally I would like to register only the CommaSeparetedCsvReader component but when an attempt is made to resolve CommaSeparetedCsvReader_Skips2Rows it should strip the suffix, parse it and change the properties accordingly.

Is it possible to somehow modify the Resolve() behavior?

Thanks, Tom


回答1:


If you are resolving your components using the TypedFactoryFacility, creating a custom ITypedFactoryComponentSelectors might help you. I would need more detail on how you create the Readers to give you more info.

Kind regards, Marwijn.

Edit =====================================

Let's add an example:

public interface IFoo
{
}

public class Foo1 : IFoo
{
}

public class Foo2 : IFoo
{
}

public interface IFooFactory
{
    IFoo CreateFoo(string which);
}

public class FooFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(MethodInfo method, object[] arguments)
    {
        return (string)arguments[0];
    }
}

--- registration

container.AddFacility<TypedFactoryFacility>();
Component.For<IFoo>().Named("Foo1Name").ImplementedBy<Foo1>(), 
Component.For<IFoo>().Named("Foo2Name").ImplementedBy<Foo2>(),
Component.For<IFooFactory>().AsFactory(f => f.SelectedWith(new FooFactoryComponentSelector())),

--- usage

var factory = _container.Resolve<IFooFactory>(); // in general this would just be a dependency in the constructor.
var foo = factory.CreateFoo("Foo2Name");

Just adapt the component selector to your needs. If necessary you can also pass additional arguments to CreateFoo, if the constructor requires arguments not provided by the container.

More info: http://docs.castleproject.org/Windsor.Typed-Factory-Facility-interface-based-factories.ashx



来源:https://stackoverflow.com/questions/14099692/resolving-dynamically-base-on-name-convention-in-castle-windsor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!