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

时间:2013-05-22 14:02:56

标签: .net inversion-of-control castle-windsor typed-factory-facility

我有以下类型的工厂:

public interface IWorkerFactory
{
    IWorker Create(IJob job);

    void Release(IWorker handler);
}

这家工厂为某项工作创造了工人。这些作业都实现IJob,但我想要一些处理不同类型作业的组件:

e.g。这两个都来自IJob

interface IJobType1 : IJob { }

interface IJobType2 : IJob { }

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

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

class Worker2 : IWorker
{
    public Worker2(IJobType2 job) { }
}

我已经尝试了这一点,但Windsor只选择了每次发现的IWorker的第一个实现,尝试将IJobType1传递给Worker2(反之亦然)例外

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

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

编辑:

尝试使用通用接口,但似乎没有给我我正在寻找的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

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

理想情况下,我想要某种方法来拦截或自定义解决方案流程,以便我可以确定接受IJob的最接近的匹配签名是什么。

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

1 个答案:

答案 0 :(得分:6)

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

枚举:

public enum JobType
{
    Type1,
    Type2
}

容器安装程序:

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>()));

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

public interface IJob
{
    JobType JobType { get; }
}

然后在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;
    }
}

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

更新04/05/18:

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