获取受cqlinq中的扩展方法影响的类型列表

时间:2015-04-06 14:03:42

标签: ndepend

如何获取ndepend cqlinq中扩展方法扩展的类型列表?使用反射代码这似乎有点驴工作,其中ndepend已经存在。

1 个答案:

答案 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 } 

正如所写,由于类型名称格式化,它是一个复杂的查询,并且它在大多数情况下都能正常工作。

NDepend Code Query Result Extension Methods

但是,在扩展泛型类型方面,它表示IEnumerable<T>扩展了IEnumerable<String>IEnumerable<Int32>两种方法。这是可以接受的,但并非100%正确。

NDepend Code Query Result Extension Methods

此外,如果您扩展了多个具有相同名称但各种通用arity的类型(例如Func<T1,T2>Func<T1,T2,T3>),那么此代码查询将无法正常工作。

如果扩展多个具有相同名称的类型,在不同的程序集或命名空间中声明(无论如何都是代码味道),也是如此。

希望这有帮助!

相关问题