Поиск всех пространств имен в сборке с использованием Reflection (DotNET)

У меня есть assembly (загружена как ReflectionOnly), и я хочу найти все пространства имен в этой сборке, чтобы я мог преобразовать их в операторы «using» («Импорт» в VB) для шаблона файла с автогенерированным исходным кодом.

В идеале я хотел бы ограничиться только верхними уровнями имен, поэтому вместо:

using System; using System.Collections; using System.Collections.Generic; 

вы получите только:

 using System; 

Я заметил, что в classе System.Type есть свойство Namespace, но есть ли лучший способ собирать пространства имен внутри сборки, не связанные с итерацией по всем типам и отбраковка повторяющихся строк пространства имен?

Очень важно, Дэвид

Нет, для этого нет ярлыка, хотя 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()); } 
  • Как точно работает инструкция x86 LOOP?
  • Как определить, была ли assembly .NET построена для x86 или x64?
  • Ошибки CocoaPods при сборке проекта
  • использование ILMerge с библиотеками .NET 4
  • Самый быстрый способ вычисления 128-битного целого по модулю 64-разрядного целого числа
  • В чем разница между MOV и LEA?
  • Динамически заменить содержимое метода C #?
  • Как загрузить сборку во время выполнения перед событием AssemblyResolve?
  • Почему медленная инструкция цикла? Не удалось ли Intel эффективно внедрить его?
  • Есть ли альтернатива Maven или порт для мира .NET?
  • Почему XCHG reg, reg 3 инструкции по микрооперации на современных архитектурах Intel?
  • Давайте будем гением компьютера.