Неуниверсальные версии универсальных классов и интерфейсов
-
05-07-2019 - |
Вопрос
Я часто нахожусь в ситуации, когда я создаю общий интерфейс или класс, а затем хочу использовать разные версии этого класса или интерфейса не универсальным способом. Например, у меня может быть такой интерфейс:
interface ICanCreate<T>
{
T NewObject();
}
Что позволяет классу быть фабрикой для этого типа. Затем я хочу зарегистрировать их в общем классе фабрики, поэтому я пытаюсь написать что-то вроде этого:
public class Factory
{
private Dictionary<Type, ICanCreate> mappings; // what do I put here????
public void RegisterCreator<T>(ICanCreate<T> creator)
{
}
public T Create<T>()
{
}
}
В словаре какой тип я использую для моего значения? Я не знаю, пропускаю ли я какой-то принцип проектирования, и я знаю, что это во многом связано с ко (ntra?) Дисперсией. Любая помощь или идеи будут высоко оценены.
Решение
Вы должны либо просто использовать object
в объявлении словаря (все это конфиденциально, и вы можете убедиться, что вы никогда не поместите туда неправильные вещи), либо объявить не -общий ICanCreate
интерфейс, который ICanCreate<T>
расширяется.
По сути, вам нужны отношения типа, которые не могут быть выражены в C # - и всякий раз, когда это происходит, вы получаете немного неприятное решение, но похоже, что вы можете изолировать уродство здесь (то есть сохранить его в одном классе ). р>
Другие советы
Интересно, что эта проблема решена в C # 4.0:
public interface ICanCreate<out T> // covariant
{
T NewObject();
}
public class Factory
{
private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>();
public void RegisterCreator<T>(ICanCreate<T> creator) where T:class
{
mappings[typeof(T)] = creator;
}
public T Create<T>()
{
ICanCreate<object> creator = mappings[typeof(T)];
return (T) creator.NewObject(); // I do not think you can get rid of this cast
}
}