[英]Using reflection to find all classes in an assembly that contain an interface by name
[英]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.