2012-05-10 3 views
2

OK Я только что применил шаблон Command-CommandHandler в нашем приложении, который добавляет объект команды в очередь; затем использует инъекцию зависимостей через Castle Windsor наряду с общим методом, чтобы получить соответствующий обработчик для объекта команды.Передача типа класса вместо интерфейса через генераторы

Интерфейс командной пустым следующим образом:

public interface ICommand 
{ 
} 

Хотя интерфейс CommandHandler обрабатывает его следующим образом:

public interface ICommandHandler<TCommand> where TCommand : ICommand 
{ 
    void Handle(TCommand command); 
} 

, которые затем реализуются с помощью команды я желаю послать через очереди; затем регистрируется в замок Виндзор через DependencyRegistration обертку так:

_dependencyRegister 
    .AddRegistration<ICommandHandler<TestCommand>, TestCommandHandler>(); 

Таким образом, каждая команда, которая будет добавлена ​​в очередь карт 1 к 1 с обработчиком; затем зарегистрирован в замке Виндзор; поэтому мы можем использовать универсальный метод, как это, чтобы получить соответствующую CommandHandler для конкретного объекта Command:

private void HandleCommand<T>(T queueItem) where T: ICommand 
{ 
    var handler = _dependencyResolver.Resolve<ICommandHandler<T>>(); 

    handler.Handle(queueItem); 
} 

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

private void DispatchQueueItem(ICommand queueItem) 
{ 
    HandleCommand(queueItem); 
} 

справа; проблема в том, что когда я вывожу команду из очереди в качестве ICommand и передаю ее методу DispatchQueueItem; когда он отправляется методу HandleCommand, тип «T» всегда устанавливается в интерфейс «ICommand»; а не фактической реализации интерфейса (TestCommand в образце кода DependencyRegistration).

Мой вопрос: как установить метод HandleCommand для реализации типа реализации; не интерфейс?

+0

Одна секунда для дублирования этой общей установки. Я подозреваю, что '' DispatchQueueItem'' '' как 'ICommand', что общий аргумент' HandleCommand' выводится из типа boxed. – Tejs

+0

Общая конструкция (T) - это временное разрешение компиляции типа. Вы ищете разрешение типа времени выполнения. Для этого вам придется использовать динамический тип или отражение. – user957902

ответ

4

изменить способ доставки в родовое:

private void DispatchQueueItem<T>(T queueItem) 
    where T: ICommand 
{ 
    HandleCommand(queueItem); 
} 

UPDATE вы можете заставить C# определить тип объекта во время выполнения таким образом

private static void DispatchQueueItem(ICommand queueItem) 
{ 
    HandleCommand((dynamic)queueItem); 
} 
+0

+1, это в основном то, что я собирался предложить. – Tejs

+0

OK Я изменил метод вызова, чтобы также использовать generics '; однако я все еще получаю эту проблему. Если это помогает; метод, который извлекает элементы ICommand перед передачей методу DispatchQueueItem, выглядит следующим образом: 'public IEnumerable Dequeue()' –

+0

Вы - семь оттенков легенды; вот и все, используя динамические силы, чтобы элемент разрешал реализованный тип, а не интерфейс. –

0

Я думаю, что вы хотите это иметь интерфейс - но вам просто нужно иметь контракт метод, определенный там - как:

public interface ICommand 
{ 
    void Execute(); 
} 

//Concrete implementation: 
public TestCommand : ICommand 
{ 
    public void Execute() 
    { 
     //Do something 
    } 
} 

Затем, когда вы получите ICommand из DI - вы можете позвонить queueItem.Execute() - и это будет означать любую конкретную реализацию, которую вы назначили.

+1

Справедливая точка; однако я хочу сохранить целостность шаблона Command - CommandHandler, как описано здесь: http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91. То, как вы описали, конечно, проще; однако в приведенной выше статье следует объяснить, почему разделение полезно. –

0

Yout очередь будет lalways диспетчерских ICommands. Поэтому так необходимо, чтобы получить тип «под капотом»:

private void HandleCommand<T>(T queueItem) where T: ICommand 
{ 
    var typeParam = queueItem.GetType(); 
    var type = typeof(ICommandHandler<>).MakeGenericType(typeParam); 
    var handler = _dependencyResolver.Resolve(type); 

Я не уверен в точном синтаксисе. У вас нет проекта с замком Виндзор под рукой.

+0

Похоже, мы приближаемся; но когда я добавляю '.Resolve (type)' или 'Resolve ' или 'Resolve >' Я получаю "Не удается разрешить символ 'type'" –

+0

Можете ли вы отладить и посмотреть, какой тип 'type'? т. е. получить 'type.FullName'. А также тип 'queueItem'. – JotaBe

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