如何获取ndepend cqlinq中扩展方法扩展的类型列表?使用反射代码这似乎有点驴工作,其中ndepend已经存在。
答案 0 :(得分:1)
NDepend代码模型没有直接的方法来解析方法参数类型。因此,我们可以提出一个令人满意的答案,依赖于字符串格式扩展类型名称的代码查询,从方法名称中提取。但是这个查询过于复杂,并且存在不能正常工作的边缘情况(如下所述)。
这是代码查询,由于使用了字典,它甚至可以在大型代码库上快速运行:
//
// First let build dicoExtensionMethods
let dicoExtensionMethods =
(from m in Application.Methods
where m.IsExtensionMethod
// extract extended type simple name (with generic parameters like "IEnumerable<String>")
let beginIndex = m.Name.IndexOf("(") + 1
let endIndex = m.Name.IndexOf(',', beginIndex) > 0 ? m.Name.IndexOf(',', beginIndex) : m.Name.IndexOf(")", beginIndex)
let extendedTypeSimpleName1 = m.Name.Substring(beginIndex, endIndex - beginIndex)
// Take care of generic type first char, like "IEnumerable<"
let extendedTypeSimpleName2 = extendedTypeSimpleName1.IndexOf('<') == -1 ? extendedTypeSimpleName1 :
extendedTypeSimpleName1.Substring(0, extendedTypeSimpleName1.IndexOf('<') + 1 )
select new { m, extendedTypeSimpleName2 })
.ToLookup(pair => pair.extendedTypeSimpleName2)
.ToDictionary(g => g.Key, g=> g.Select(p =>p.m))
//
// Second for each type get extension methods from dicoExtensionMethods
from t in Types
// Format type name like "IEnumerable<"
let typeName = !t.IsGeneric ? t.SimpleName : t.Name.Substring(0, t.Name.IndexOf('<') + 1 )
where dicoExtensionMethods.ContainsKey(typeName)
let methods = dicoExtensionMethods[typeName]
select new { t, methods }
正如所写,由于类型名称格式化,它是一个复杂的查询,并且它在大多数情况下都能正常工作。
但是,在扩展泛型类型方面,它表示IEnumerable<T>
扩展了IEnumerable<String>
和IEnumerable<Int32>
两种方法。这是可以接受的,但并非100%正确。
此外,如果您扩展了多个具有相同名称但各种通用arity的类型(例如Func<T1,T2>
和Func<T1,T2,T3>
),那么此代码查询将无法正常工作。
如果扩展多个具有相同名称的类型,在不同的程序集或命名空间中声明(无论如何都是代码味道),也是如此。
希望这有帮助!