使用反射发现装配中的所有命名空间(DOTNET)(Finding all Namespaces in

2019-07-21 22:11发布

我有一个组件(加载ReflectionOnly),我想找到这个程序集中的所有命名空间,所以我可以将它们转换成“使用”的自动生成的源代码文件模板(在VB“进口”)语句。

理想情况下,我想自己限制在顶级命名空间而已,所以不是:

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

你只能得到:

using System;

我注意到有上的System.Type类命名空间属性,但有没有更好的方式来收集,不涉及遍历所有类型和剔除重复的命名空间字符串的组件内部命名空间?

非常感谢,大卫

Answer 1:

没有,有这个没有捷径,虽然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);
}

我很好奇,为什么你只需要最高级别的命名空间,但...这似乎是一个奇怪的约束。



Answer 2:

命名空间实际上只是在类型名称的命名约定,所以他们只“存在”为跨很多合格的类型名称重复的模式。 所以,你通过所有的类型都循环。 然而,这样做的代码大概可以写成一个单一的LINQ表达式。



Answer 3:

这里有一个排序的linq'ish方式,但它仍然在本质上是每一个元素itterating结束了,但代码干净多了。

var nameSpaces = from type in Assembly.GetExecutingAssembly().GetTypes()
                 select  type.Namespace;
nameSpaces = nameSpaces.Distinct();

此外,如果你的汽车产生的代码,你可能会更好完全限定的一切,那么你就不必担心命名在生成的代码冲突。



Answer 4:

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);
}


Answer 5:

您将没有其他选择,比遍历所有类。

需要注意的是进口不递归工作。 “使用系统”不会像从System.Collections中或System.Collections.Generic子命名导入任何类,而是你必须包括他们所有。



Answer 6:

public static void Main() {

    var assembly = ...;

    Console.Write(CreateUsings(FilterToTopLevel(GetNamespaces(assembly))));
}

private static string CreateUsings(IEnumerable<string> namespaces) {
    return namespaces.Aggregate(String.Empty,
                                (u, n) => u + "using " + n + ";" + Environment.NewLine);
}

private static IEnumerable<string> FilterToTopLevel(IEnumerable<string> namespaces) {
    return namespaces.Select(n => n.Split('.').First()).Distinct();
}

private static IEnumerable<string> GetNamespaces(Assembly assembly) {
    return (assembly.GetTypes().Select(t => t.Namespace)
            .Where(n => !String.IsNullOrEmpty(n))
            .Distinct());
}


文章来源: Finding all Namespaces in an assembly using Reflection (DotNET)