Простое заявление о том, что «Reflection» работает медленно, превращает адскую массу функциональных возможностей в очень широкое одеяло. Отражение в .NET состоит из нескольких классов, каждый с разным уровнем «производительности». Например, использование оператора typeof()
на самом деле является формой отражения ... он запрашивает метаданные CLR для типа. Однако typeof()
выполняется очень быстро (в почти свободное время). Использование других «отражений», связанных с типом, таких как оператор is, оператор sizeof()
и т. Д., Также почти бесплатны (в основном они работают так, как будто они были статические коды.)
Отражение, используемое для извлечения информации о типе, хотя и медленнее, чем typeof()
, также очень и очень быстро, учитывая количество обхода указателя и проверку метаданных. Зондирование метаданных является довольно распространенной практикой для кода .NET, особенно когда речь идет о работе с пользовательскими атрибутами.
Большая проблема производительности в отношении рефлексии связана с вызовом. Доступ к информации о типе и чтение метаданных довольно легки. В тот момент, когда вы задействуете динамический вызов свойств, индексаторов, методов или динамически создаете новые типы с помощью отражения, вы получаете прирост производительности на порядки.
Отражение по-прежнему выполняется внутри процесса, поэтому, прежде чем беспокоиться о снижении производительности при небольшом динамическом вызове, убедитесь, что отсутствуют какие-либо значительно более узкие места производительности, такие как межпроцессное выполнение, сетевые вызовы. (т. е. база данных, веб-служба и т. д.). Когда дело доходит до производительности, начните с наибольшего снижения производительности и продолжайте свой путь оттуда. Отражение, включая динамический вызов, обычно является одной из последних вещей, о которой вам следует беспокоиться с точки зрения производительности.
Добавление:
Немного запоздалая мысль, но если вам требуется высокая степень динамического вызова членов типа с поздней привязкой, вам следует взглянуть на упрощенную генерацию кода. Используя пространство имен System.Reflection.Emit, вы можете использовать такие утилиты, как DynamicMethod, для генерации облегченного кода во время выполнения, который может выполнять вызовы с ранней привязкой. Кэширование этого сгенерированного кода снижает первоначальные затраты на его генерацию, позволяя вам получить выгоду от вызовов с поздней связью и производительностью с ранней связью.