Какие проблемы решается?
Я просмотрел все сообщения на reflection, но не смог найти ответ на мой вопрос.
Каковы были проблемы в мире программирования перед .NET-анализом
пришел и как он решил эти проблемы?
Пожалуйста, объясните пример.
Ответы
Ответ 1
Следует отметить, что отражение .NET не является революционным - концепции существуют в других рамках.
Отражение в .NET имеет 2 грани:
Информация о типе исследования
Без какого-либо API-интерфейса для отражения/интроспекции становится очень сложно выполнять такие вещи, как сериализация. Вместо того, чтобы это предоставлялось во время выполнения (путем проверки свойств/полей/etc), вам часто требуется генерация кода, то есть код, который явно знает, как сериализовать каждый из ваших типов. Занудный и болезненный, если вы хотите сериализовать то, что не имеет близнеца.
Аналогичным образом, хранить метаданные о свойствах и т.д. некуда, поэтому у вас будет много дополнительного кода или внешних файлов конфигурации. Что-то простое, как возможность сопоставить дружественное имя с свойством (через атрибут) - огромная победа для кода пользовательского интерфейса.
Метапрограммирование
.NET reflection также предоставляет механизм для создания типов (и т.д.) во время выполнения, что чрезвычайно эффективно для некоторых конкретных сценариев; альтернативы:
- по существу работает дерево парсера/логики во время выполнения (а не компиляция логики во время выполнения в исполняемый код) - гораздо медленнее
- еще больше генерации кода - yay!
Ответ 2
Я думаю, что для понимания необходимости отражения в .NET нам нужно вернуться к .NET. В конце концов, современные языки, такие как Java и С#, не имеют BF истории (перед отражением).
С++, возможно, оказал наибольшее влияние на С# и Java. Но у С++ изначально не было отражения, и мы закодировали без него, и нам удалось пройти. Иногда у нас был указатель void, и он использовал бы бросок, чтобы заставить его в любой тип, который мы хотели. Проблема здесь заключалась в том, что бросок может потерпеть неудачу с ужасными последствиями:
double CalculateSize(void* rectangle) {
return ((Rect*)rectangle)->getWidth() * ((Rect*)rectangle)->getHeight());
}
Теперь есть много аргументов, почему вы не должны были кодировать себя в эту проблему в первую очередь. Но проблема не сильно отличается от .NET 1.1 с С#, когда у нас не было дженериков:
Hashtable shapes = new Hashtable();
....
double CalculateSize(object shape) {
return ((Rect)shape).Width * ((Rect)shape).Height;
}
Однако, когда пример С# не работает, он делает это с исключением, а не с потенциальным ядром ядра.
Когда отражение было добавлено в С++ (известное как идентификация типа времени выполнения или RTTI), это было горячо обсуждено. В книге Страуступа "Дизайн и эволюция C++" он перечисляет следующие
аргументы против RTTI, в том, что некоторые люди:
Declared the support unnecessary
Declared the new style inherently evil ("against the spirit of C++")
Deemed it too expensive
Thought it too complicated and confusing
Saw it as the beginning of an avalanche of new features
Но это позволило нам запросить тип объектов или объекты объектов. Например (используя С#)
Hashtable shapes = new Hashtable();
....
double CalculateSize(object shape) {
if(shape is Rect) {
return ((Rect)shape).Width * ((Rect)shape).Height;
}
else if(shape is Circle) {
return Math.Power(((Circle)shape).Radius, 2.0) * Math.PI;
}
}
Конечно, при правильном планировании этот пример никогда не должен возникать.
Итак, ситуации реального мира, в которых я нуждался, включают:
- Доступ к объектам из разделяемой памяти, все, что у меня есть, - это указатель, и мне нужно решить, что с ним делать.
- Динамически загружая сборки, подумайте о NUnit, где он загружает каждую сборку и использует отражение, чтобы определить, какие классы являются тестовыми приборами.
- Наличие смешанного пакета объектов в Hashtable и желание обрабатывать их по-разному в счетчике.
- Многие другие...
Итак, я хотел бы догадаться, что Reflection не позволил сделать что-то, чего раньше нельзя было сделать. Тем не менее, он делает некоторые типы проблем более легкими для кодирования, более четкими для читателя, короткими для записи и т.д.
Конечно, только мое мнение, я могу ошибаться.
Ответ 3
Мне когда-то хотелось иметь модульные тесты в текстовом файле, которые могут быть изменены нетехническим пользователем в формате на С++:
MyObj Function args //textfile.txt
Но я не мог найти способ чтения в строке, а затем создать код экземпляра объекта типа, представленного строкой, без отражения, которое С++ не поддерживает.
char *str; //read in some type from a text file say the string is "MyObj"
str *obj; //cast a pointer as type MyObj
obj = new str; //create a MyObj
Другим вариантом может быть создание универсальной функции копирования, которая могла бы скопировать членов класса, не зная их заранее.
Ответ 4
Это очень помогает, когда вы используете в своем коде атрибуты С#, такие как [Устаревшие] или [Serializable]. Такие структуры, как NUnit, используют отражение в классах и содержат методы для понимания того, какие методы являются испытаниями, установкой, разрывом и т.д.