获取由cqlinq中的扩展方法影响的类型的列表 [英] Getting list of types that are effected by an extension method in cqlinq

查看:81
本文介绍了获取由cqlinq中的扩展方法影响的类型的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取由ndepend cqlinq中的扩展方法扩展的类型的列表?使用反射进行编码似乎在ndepend已经存在的地方有点驴工作.

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.

推荐答案

NDepend代码模型没有解决方法参数类型的直接方法.因此,我们可以依靠从方法名称中提取的字符串格式扩展类型名称来为代码查询提供满意的答案.但是此查询过于复杂,并且在某些极端情况下无法正常工作(如下所述).

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.

但是,当涉及到扩展泛型类型时,例如说IEnumerable<T>由扩展IEnumerable<String>IEnumerable<Int32>的两种方法扩展.这是可以接受的,但并非100%正确.

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.

此外,如果您扩展具有相同名称但具有各种通用Arity的几种类型(例如Func<T1,T2>Func<T1,T2,T3>),则此代码查询将无法正常工作.

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).

希望这会有所帮助!

这篇关于获取由cqlinq中的扩展方法影响的类型的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆