我有以下类型的工厂:
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
的所有实现者并确定哪些构造函数与最接近的参数匹配,但是,如何解析此实例中的容器,因为我没有要使用的容器实例?我真的不喜欢让容器静止的想法
答案 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在评论中提到的那样,你还需要在容器中注册选择器,因为它将使用容器来解析选择器。