簡體   English   中英

使用Reflection(DotNET)查找程序集中的所有命名空間

[英]Finding all Namespaces in an assembly using Reflection (DotNET)

我有一個程序集(作為ReflectionOnly加載),我想找到這個程序集中的所有命名空間,所以我可以將它們轉換為自動生成的源代碼文件模板的“using”(VB中的“Imports”)語句。

理想情況下,我只想將自己限制在頂級命名空間,而不是:

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

你只會得到:

using System;

我注意到System.Type類上有一個Namespace屬性,但有沒有更好的方法來收集程序集內的Namespaces,它不涉及迭代所有類型並剔除重復的命名空間字符串?

大衛,很有責任

不,這沒有捷徑,雖然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);
}

除了迭代所有類之外別無選擇。

請注意,導入不會遞歸。 “using System”不會從System.Collections或System.Collections.Generic等子名稱空間導入任何類,而是必須包含所有類。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM