Getting list of types that are effected by an extension method in cqlinq

僤鯓⒐⒋嵵緔 提交于 2019-12-20 03:03:36

问题


How to get the list of types that are extended by a extension method in ndepend cqlinq? Using reflection to code this seems a bit of donkey work where ndepend is already there.


回答1:


NDepend code model doesn't have a straight way to resolve the method parameter type. So we can come up with a satisfying answer with code query relying on string formatting extended type name, extracted from the method name. But this query is overly complex and there are edge cases where it won't work properly (explained below).

Here is the code query, it runs fast even on large code base thanks to the use of a dictionary:

//
// 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 } 

As written it is a complex query because of type name formatting, and it works fine most of the time.

However when it comes to extending generic types, it says for example that IEnumerable<T> is extended by both methods that extend IEnumerable<String> and IEnumerable<Int32>. This is acceptable, but it is not 100% correct.

Also if you extend several types with same name but various generic arity (like Func<T1,T2> and Func<T1,T2,T3>), then this code query won't work properly.

The same if you extend several types with same name, declared in different assemblies or namespace (which is a code smell anyway).

Hope this helps!



来源:https://stackoverflow.com/questions/29472845/getting-list-of-types-that-are-effected-by-an-extension-method-in-cqlinq

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!