3

我有以下类型的工厂:

public interface IWorkerFactory
{
    IWorker Create(IJob job);

    void Release(IWorker handler);
}

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

例如,这两个都源自IJob

interface IJobType1 : IJob { }

interface IJobType2 : IJob { }

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

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

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

我已经尝试过了,但是 Windsor 只是IWorker每次都选择它找到的第一个实现,尝试传递一个IJobType1to 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并确定哪些构造函数与最接近的参数匹配,但是,我如何从该实例中的容器解析,因为我没有要使用的容器实例?我真的不喜欢使容器静态的想法

4

1 回答 1

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;
    }
}

这样我就不需要到处寻找任何常量,如果我需要新的工作类型,我可以将它们粘贴在枚举上,并让工作根据它们的实现自动关联起来。

2018 年 4 月 5 日更新:

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

于 2013-05-22T16:19:03.777 回答