如何在n依赖性cqlinq中获得由扩展方法扩展的类型列表?使用反射来编写代码,这似乎是一项有点繁琐的工作,因为n依赖性已经存在了。
发布于 2015-04-07 07:14:02
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%正确的。

另外,如果您扩展了几个同名但不同泛型的类型(如Func<T1,T2>和Func<T1,T2,T3>),则此代码查询将无法正常工作。
如果您扩展几个名称相同的类型,在不同的程序集或命名空间中声明这些类型(无论如何,这都是一种代码气味),则相同。
希望这能有所帮助!
https://stackoverflow.com/questions/29472845
复制相似问题