Поиск всех пространств имен в сборке с использованием Reflection (DotNET)
У меня есть assembly (загружена как ReflectionOnly), и я хочу найти все пространства имен в этой сборке, чтобы я мог преобразовать их в операторы «using» («Импорт» в VB) для шаблона файла с автогенерированным исходным кодом.
В идеале я хотел бы ограничиться только верхними уровнями имен, поэтому вместо:
using System; using System.Collections; using System.Collections.Generic;
вы получите только:
- Maven: добавьте зависимость к банке относительным путем
- Как точно работает инструкция x86 LOOP?
- Как объединить несколько сборок в один?
- Как я могу перечислить все загруженные сборки?
- Загрузка нескольких версий одной и той же сборки
using System;
Я заметил, что в classе System.Type есть свойство Namespace, но есть ли лучший способ собирать пространства имен внутри сборки, не связанные с итерацией по всем типам и отбраковка повторяющихся строк пространства имен?
Очень важно, Дэвид
- Как сохранить сборки ASP.NET в AppDomain в живых?
- Определите, были ли сборки .NET построены из одного источника
- Ошибки CocoaPods при сборке проекта
- Visual Studio 2010: ссылочные сборки Ориентация на версию с более высокой версией
- Как определить, была ли assembly .NET построена для x86 или x64?
- Почему mulss занимает всего 3 цикла на Хасуэлле, отличном от таблиц инструкций Агнера?
- Сколько циклов процессора требуется для каждой инструкции сборки?
- Почему XCHG reg, reg 3 инструкции по микрооперации на современных архитектурах Intel?
Нет, для этого нет ярлыка, хотя LINQ делает это относительно легко. Например, в C # необработанный «набор пространств имен» будет:
var namespaces = assembly.GetTypes() .Select(t => t.Namespace) .Distinct();
Чтобы получить пространство имен верхнего уровня, вы должны, вероятно, написать метод:
var topLevel = assembly.GetTypes() .Select(t => GetTopLevelNamespace(t)) .Distinct(); ... static string GetTopLevelNamespace(Type t) { string ns = t.Namespace ?? ""; int firstDot = ns.IndexOf('.'); return firstDot == -1 ? ns : ns.Substring(0, firstDot); }
Я заинтригован, почему вам нужны только пространства имен верхнего уровня, хотя … это кажется странным ограничением.
Пространства имен – это просто соглашение об именах в именах типов, поэтому они только «существуют» как шаблон, который повторяется во многих квалифицированных именах типов. Таким образом, вам нужно пройти все типы. Однако код для этого, вероятно, может быть записан как одно выражение Linq.
Вот своего рода linq’ish путь, он по-прежнему по сути повторяется над каждым элементом, но код намного чище.
var nameSpaces = from type in Assembly.GetExecutingAssembly().GetTypes() select type.Namespace; nameSpaces = nameSpaces.Distinct();
Кроме того, если вы создаете код генерации кода, вам может быть лучше, чтобы полностью квалифицировать все, тогда вам не придется беспокоиться об именовании конфликтов в сгенерированном коде.
Немного LINQ?
var qry = (from type in assembly.GetTypes() where !string.IsNullOrEmpty(type.Namespace) let dotIndex = type.Namespace.IndexOf('.') let topLevel = dotIndex < 0 ? type.Namespace : type.Namespace.Substring(0, dotIndex) orderby topLevel select topLevel).Distinct(); foreach (var ns in qry) { Console.WriteLine(ns); }
У вас не будет другого выбора, кроме повторения всех classов.
Обратите внимание, что импорт не работает рекурсивно. «using System» не будет импортировать какие-либо classы из подзонных пространств, таких как System.Collections или System.Collections.Generic, вместо этого вы должны включить их все.
public static void Main() { var assembly = ...; Console.Write(CreateUsings(FilterToTopLevel(GetNamespaces(assembly)))); } private static string CreateUsings(IEnumerable namespaces) { return namespaces.Aggregate(String.Empty, (u, n) => u + "using " + n + ";" + Environment.NewLine); } private static IEnumerable FilterToTopLevel(IEnumerable namespaces) { return namespaces.Select(n => n.Split('.').First()).Distinct(); } private static IEnumerable GetNamespaces(Assembly assembly) { return (assembly.GetTypes().Select(t => t.Namespace) .Where(n => !String.IsNullOrEmpty(n)) .Distinct()); }