Тот, кто работал когда-нибудь с Reflection в .NET, тот наверняка мучился, когда вставала задача, к примеру перебора или поиска типов. Нужно подгружать сборку в домен, после чего, вероятно, можно будет перебирать метаданные сборки. Почему «возможно» ? Потому что сборка может быть не загружена в домен, например из-за зависимых сборок, которые должны быть загружены в домен ранее, или расположены где то «рядом» с приложением. Кроме того, говорят что производительность Reflection несколько слабовата. Правда это или нет, другой вопрос, я натыкался только на упоминания о том, что выполнение кода через Reflection медленней в 3-4 раза (отсюда).
А недавно я наткнулся на одно незначительное упоминание о такой штуке, как Common Compiler Infrastructure: Metadata API.
Приведу просто выдержку с главной страницы codeplex, где этот проект лежит в исходниках:
Microsoft Research Common Compiler Infrastructure (CCI) is a set of libraries and an application programming interface (API) that supports some of the functionality that is common to compilers and related programming tools.
The CCI Metadata API allows applications to efficiently analyze or modify .NET assemblies, modules, and debugging (PDB) files. CCI Metadata supports the functionality of the .NET System.Reflection and System.Reflection.Emit APIs, but with much better performance. It also provides additional functionality that is not available in either .NET API.
Если в общем, то это подобие Reflection, только значительно производительней.
В дополнение к нему, есть другой проект на том же Codeplex - Common Compiler Infrastructure: Code Model and AST API.
The Common Compiler Infrastructure (CCI) is a collection of frameworks for working with .NET source code, assemblies, modules, and debug files. In part, CCI supports a more efficient version of the functionality provided by System.Reflection, System.Reflection.Emit, and System.CodeDom. However, CCI goes beyond those components to provide a unified framework for static analysis and rewriting of assembly metadata and code. CCI supports a broad range of scenarios, including:
· Compilers, which start with source code and transform it to .NET assemblies and modules.
· Static analysis tools, which analyze the contents of .NET assemblies.
· Rewriting tools, which add code or metadata to assemblies or modify existing code or metadata.
В кратце, это уже коллекция фреймворков для работы с исходниками, сборками, модулями и отладочной информацией. И вроде бы с их помощью работают такие вещи, как FxCop и Code contracts tool.
Посмотреть я решил в сторону работы с метаданными, вот что получилось. Сразу оговорюсь, что сравнивать с Reflection я тут не буду, тот, кто хочет, может сам написать такой же код на Reflection и проверить. Я не стал этим заниматься.
Итак, задачка:
По списку строк, содержащих имена фалов сборок получить:
1. Имя сборки.
2. Все типы, содержащиеся в этой сборке.
3. Все members типа: свойства, методы.
Вот такой код получился при использовании Cci. Просто и со вкусом…
MetadataReaderHost host = new PeReader.DefaultHost();
foreach (string assemblyName in references)
{
IAssembly assembly = host.LoadUnitFrom(assemblyName) as IAssembly;
if (assembly == null) continue;
string assname = assembly.Name.Value;
foreach (INamedTypeDefinition type in assembly.GetAllTypes())
{
if (type == null) continue;
string s = type.Name.Value;
foreach (IMethodDefinition method in type.Methods)
{
if (method == null) continue;
string m = method.Name.Value;
}
}
}
В списке references лежат имена файлов сборок по которым идет перебор. Для начала я натравил эту утилиту на примерно 30 сборок самого Cci, но результат в 300 мс, хотя и с небольшим разбросом мне почему то не понравился и я решил натравить на сборки в папке Microsoft.NET\Framework\v4.0.30319. В этой папочке конечно лежат не только .NET сборки, поэтому нормально обработать удалось только 112 сборок.
Мне кажется, что результат в 5 сек для 38 000 типов достаточно хорош. Интересно, каких результатов можно добиться с использованием Reflection?..
Posted via email from Комуникликабельность