C#: System.Type не является реальным типом? или: работа вокруг одной отправки
Я пытался обойти C# без полиморфной отправки, основанной на типе аргумента метода, и я столкнулся с тем, что вы не можете передавать типы.
У меня в основном есть абстрактный класс Model
который реализует два метода: IEnumerable<Decision> GetDecisions()
а также void TakeDecision(Decision decision)
, Decision
это также абстрактный класс. Потребитель этого класса неоднократно получает возможные решения, оценивает их и передает лучшее обратно Model
,
Каждая отдельная производная модель может работать с некоторыми общими решениями и некоторыми решениями, специфичными для модели, и у меня есть отдельный TakeDecision()
метод для каждого Decision
введите этот конкретный Model
может работать с Проблема, конечно, с одной отправкой. В идеале, потребитель сделал бы это:
var m = ModelFactory.GetModel(some parameters); //m is type Model
var ds = m.GetDecisions(); //ds is IEnumerable<Decision>
//Some logic here to choose the best Decision d
m.TakeDecision(d);
Теперь я должен реализовать логику, которая выглядит так в каждом производном Model
потому что C# может отправлять на правильный Model
реализация, но не до правильной перегрузки:
if (decision is FooDecision) TakeDecision((FooDecision)decision);
if (decision is BarDecision) TakeDecision((BarDecision)decision);
...
или я заставляю потребителя выполнять кастинг на своей стороне (скорее всего, он уже сделал это, чтобы изучить решение).
Я хотел бы иметь список System.Type
s в каждом производном классе, поэтому я мог бы сделать это:
foreach (var t in AllowedDecisionTypes) {
if (decision is t) TakeDecision((t)decision);
}
но похоже System.Type
не настоящий тип:
- Вы не можете сделать это:
AllowedDecisionTypes.Add(FooDecision)
, но вы можете сделатьAllowedDecisionTypes((new FooDecision()).GetType())
- И наоборот, вы не можете сделать
decision is AllowedDecisionTypes[0]
, но вы можете сделатьdecision is FooDecision
,
Есть ли способ иметь оба? Т.е. генерировать список типов и приводить к ним? Или единственный выход сделать двойную диспетчеризацию и реализовать void Decision.ApplyTo(Model model) { model.TakeDecision(this); }
на каждое решение, которое, вероятно, должно отправлять с корректной перегрузкой, так как this
сейчас конкретный Decision
?
2 ответа
Чтобы добавить Type
к списку Type
объекты, которые вам просто нужно использовать typeof
оператор вместо простого добавления типа.
Эквивалентная операция is
для Type
объекты должны использовать его IsAssignableFrom
метод.
Вы не сможете разыграть объект на основе Type
; способ вызова одной из нескольких перегрузок на основе Type
через отражение.
Type
это объект, описывающий определенный тип, но это не сам тип, если мы посмотрим на него так: String != typeof(String)
,
Что вы можете сделать, это:
// Add type to collection of Type
AllowedDecisionTypes.Add(typeof(FooDecision))
// Check if the current decision EXACTLY of the same type
if(myDecision.GetType() == AllowedDecisionTypes[0])
// Check if the current decision inherits/implements that type (like using the 'is' operator)
if(AllowedDecisionTypes[0].IsAssignableFrom(myDecision.GetType()))