1

У меня есть следующий набранный завод:Windsor TypedFactoryFacility, выбрав компонент на основе аргументов типа

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 он находит каждый раз, пытаясь передать IJobType1 в Worker2 (или наоборот), который выдает исключение

Я посмотрел на выбранный заводской компонентный выбор или, но я не могу понять, как я буду использовать это для предполагаемого эффекта.

Возможно ли это, или лучше попытаться использовать общий интерфейс для моих рабочих классов?

Edit:

Пробовал используя общий интерфейс, но это, кажется, не дает мне 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 и определить, какие конструкторы соответствуют ближайшим аргументам, однако как я могу решить проблему из контейнера в этом экземпляре, поскольку у меня не будет экземпляра контейнера для использования? Мне не очень нравится идея сделать контейнер статическим

ответ

5

ОК Я понял, что это один из них - мне нужны два типа 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; 
    } 
} 

Таким образом, мне не нужно таскать все константы, и если мне нужны новые типы заданий, я могу просто наклеить их на перечисление и имеют рабочие места ассоциировать себя автоматически на основе их реализации.

Смежные вопросы