В C #, как я могу понизить ранее выгруженный объект, не зная его типа? - PullRequest
1 голос
/ 02 декабря 2008

У меня есть метод интерфейса

  public void Execute(ICommand command);

, который должен передать известные подтипы ICommand в соответствующую реализацию Handle(SpecificCommand command) метода и выполнить некоторую общую обработку неизвестных типов. Я ищу универсальный (т. Е. Не требующий гигантского переключателя) способ сделать это, похожий на

  Handle(command as command.GetType()); // this obviously does not compile

Я знаю, что мог бы как-то зарегистрировать обработчики, например, сохраняйте их как делегаты в словаре, но для этого все равно требуется дублирование логики обработки (один раз в сигнатуре конкретного метода Handle(...), один раз при повторной регистрации делегата). Если я заполню словарь, осмотрев мой класс с отражением (ища Handle(XXX command) методы), я получу удар по производительности.

Подводя итог: как я могу уменьшить значение объекта (повышенное с помощью вызова Execute(ICommand command)) для вызова метода, требующего конкретного типа, не зная, какой это тип во время компиляции.

Ответы [ 4 ]

9 голосов
/ 02 декабря 2008

Итак, «правильный» ответ заключается в том, что Handle () должен быть методом в ICommand, так что вместо Handle(command) вы бы сказали: command.Handle().

5 голосов
/ 02 декабря 2008

Приведение генерируется во время компиляции, поэтому вам нужно знать тип во время компиляции. Перегрузка также определяется во время компиляции - поэтому к тому моменту, когда вы на самом деле знаете конкретный тип для использования, уже слишком поздно.

Я не вижу, чтобы вы на самом деле дублировали любую логику , используя делегатов. В качестве альтернативы, если вы делаете это с помощью рефлексии, вы можете очень легко создавать делегатов с помощью Delegate.CreateDelegate - вы получите удар по производительности только один раз, и после этого он будет очень быстрым. См. Мою запись в блоге о Delegate.CreateDelegate для получения дополнительной информации.

Думаю, я бы решил использовать словарь, созданный вручную, или словарь, созданный с учетом того, сколько у меня было методов и как часто они меняются. Возможно, вы найдете KeyedByTypeCollection полезным для словаря.

2 голосов
/ 02 декабря 2008

Вы не можете, и почему вы хотите?

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

1 голос
/ 02 декабря 2008

Я пытался найти способ, который бы работал с использованием Double Dispatch (http://en.wikipedia.org/wiki/Double_dispatch),), но, похоже, у вас есть ситуация, когда число классов, реализующих ICommand, и классов, реализующих Execute (), может изменяться во время выполнения. время (или, по крайней мере, между компиляцией и временем выполнения, что по сути то же самое), поэтому единственное решение, которое я вижу, это использование словаря, как предложил Джон Скит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...