Windsor TypedFactoryFacility,根据参数类型选择组件

Cha*_*leh 3 .net castle-windsor inversion-of-control typed-factory-facility

我有以下类型的工厂:

public interface IWorkerFactory
{
    IWorker Create(IJob job);

    void Release(IWorker handler);
}
Run Code Online (Sandbox Code Playgroud)

这家工厂为特定工作创造了工人.所有工作都实现了,IJob但我想要一些处理不同类型工作的组件:

例如,这两者都来源于 IJob

interface IJobType1 : IJob { }

interface IJobType2 : IJob { }
Run Code Online (Sandbox Code Playgroud)

我想要两种工人类型,一种处理每种类型 IJob

class Worker1 : IWorker
{
    public Worker1(IJobType1 job) { }
}

class Worker2 : IWorker
{
    public Worker2(IJobType2 job) { }
}
Run Code Online (Sandbox Code Playgroud)

我已经试过这一点,但只是温莎拿起第一个实现的IWorker找到每一次,试图传递一个IJobType1Worker2(反之亦然),它抛出一个异常

我已经查看了类型化的工厂组件选择器,但我无法弄清楚如何将其用于预期的效果

这是可能的,还是尝试为我的工人类使用通用接口更好?

编辑:

尝试使用通用接口但似乎没有给我我正在寻找的API ...关键问题是我真的不想知道它是什么类型IJob但我想要最合适的IWorker实例是在解决时创建.

我这样称呼它:

public void ProcessItem(IJob job)
{
    IProcessingExceptionLog exLog = null;
    IWorker worker = null;

    try
    {
        worker = _workerFactory.Create(job);

        // Attempt to process                
        worker.Process();
    }
    catch (Exception ex) .... etc
Run Code Online (Sandbox Code Playgroud)

即使我将作业转换为更加派生的界面,Windsor仍然会选择第一个IWorker ...它对检查方法的参数不感兴趣

理想情况下,我喜欢拦截或自定义解决过程的一些方法,以便我可以确定接受的最接近的匹配签名IJob是什么.

我可以尝试自己实现基于IWorkerFactory界面的混凝土工厂.它可以查看所有实现者IWorker并确定哪些构造函数与最接近的参数匹配,但是,如何解析此实例中的容器,因为我没有要使用的容器实例?我真的不喜欢让容器静止的想法

Cha*_*leh 6

好吧我想出了这个 - 我想要两种类型,IWorker但我真的不想使用组件命名.我最终使用组件命名,但基于枚举,因为这已经是IJob我的一部分,我使用它作为我的组件选择器的一部分来确定使用哪个命名组件:

枚举:

public enum JobType
{
    Type1,
    Type2
}
Run Code Online (Sandbox Code Playgroud)

容器装置:

container.Register(Component.For<IWorker>()
                            .ImplementedBy<Worker1>()
                            .Named(JobType.Type1.ToString()));

container.Register(Component.For<IWorker>()
                            .ImplementedBy<Worker2>()
                            .Named(JobType.Type2.ToString()));

// And the factory:
container.Register(Component.For<IWorkerFactory>()
                            .AsFactory(x => x.SelectedWith<WorkerFactorySelector>()));
Run Code Online (Sandbox Code Playgroud)

然后IJob我实际上已经有了枚举:

public interface IJob
{
    JobType JobType { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后在WorkerFactorySelector:

public class WorkerFactorySelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
    {
        var job = arguments[0] as IJob;

        if (job != null)
            return job.JobType.ToString();

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样我就不需要对任何常量进行操作,如果我需要新的工作类型,我可以将它们粘贴在枚举上,让工作根据它们的实现自动关联.

更新04/05/18:

正如Edu在评论中提到的那样,你还需要在容器中注册选择器,因为它将使用容器来解析选择器.