Создание подкласса на основе ввода ввода чтения - PullRequest
0 голосов
/ 22 декабря 2018

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

Я пришел к странной конструкции, которая кажется действительно ужасной, но я неНе знаю, есть ли другой способ справиться с этим.

Код выглядит примерно так:

int type = reader.readInt32():
BaseClass p = BaseClass.Instantiate((BaseClassEnum)type);
object.Read(reader);

Этот код кажется хорошим, и это так, но BaseClass.Instantiate (BaseClassEnumМетод type) оставляет желать лучшего.

По сути, это гигантский оператор case switch, который создает подкласс базового класса в соответствии с переданным параметром type.

Есть ли способ избежать переключениядело здесь?Могу ли я создать словарь, в котором я сопоставлю BaseClassEnum с некоторой ссылкой на класс, которая позволит мне вызывать его конструктор?Что-то вроде:

Dictionary<int, ???> bindings = new Dictionary<int, ???>(){
    {BaseClassEnum1, SubClass1},
    {BaseClassEnum2, SubClass2}
}

//...

//Assuming SubClass1 has a constructor SubClass1()
BaseClass p = new bindings[BaseClassEnum1]();

//I could even create a new constructor SubClass(BinaryReader reader) and do
BaseCoass p = new bindings[BaseClassEnum1](reader);

В конце код будет выглядеть примерно так:

BaseClass p = new bindings[(BaseClassEnum)reader.ReadInt32()](reader);

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

Фабрика классов / типов (то, что вы создаете) реализуется одним из четырех основных способов.

  1. Оператор Switch или эквивалентный или серия операторов if / then / else
  2. Словарь или другая структура, которая позволяет отображать значение для определенного типа
  3. Некоторые вариации вызова по имени (что в C # означает отражение)
  4. Подписка на события (не очень часто используется), который, вероятно, будет использовать один из других методов для внутреннего использования.

Операторы Switch уродливы и, конечно, в некоторой степени подвержены ошибкам, словари примерно такие же уродливые и имеют свои собственные ошибки, но их проще тестировать.Отражение обычно медленнее, а подписка на события еще медленнее.

Таким образом, серебряной пули нет.

То, что вы описываете, будет выглядеть так:

var binding = new Dictionary<int, Func<BaseClass>>(){{BaseClassEnum1, ()=> new SubClass1()},
                                                   {BaseClassEnum2, ()=>new SubClass2()}};


var p = new bindings[BaseClassEnum1]();

Рабочий примерв https://dotnetfiddle.net/rWwCjw (с небольшой разницей в именах переменных).

Следует отметить, что и выше, и пример немного упрощены, в частности, если предполагается, что они охватывают все возможныеПодклассы в вашем приложении, словарь должен быть его собственным свойством / функцией, чтобы вы могли проверить (через отражение), что все подклассы в вашем приложении присутствуют в списке.

0 голосов
/ 22 декабря 2018

Если вы поменяете вопросительные знаки ???Type можно использовать var p = Activator.Createinstance(binding[BaseClassEnum1], reader)

Activator.Createinstance

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