为了账号安全,请及时绑定邮箱和手机立即绑定

识别扩展方法的思考

识别扩展方法的思考

C#
慕运维8079593 2019-08-12 16:10:45
识别扩展方法的思考在C#中是否有一种使用反射来确定方法是否已作为扩展方法添加到类的技术?给定一个扩展方法,如下所示,可以确定Reverse()已被添加到字符串类?public static class StringExtensions{     public static string Reverse(this string value)     {         char[] cArray = value.ToCharArray();         Array.Reverse(cArray);         return new string(cArray);     }}我们正在寻找一种机制,在单元测试中确定扩展方法是由开发人员适当添加的。尝试这种情况的一个原因是,开发人员可能会在实际的类中添加类似的方法,如果是,编译器将选择该方法。
查看完整描述

3 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

这将返回某种类型中定义的所有扩展方法的列表,包括通用类型:

public static IEnumerable<KeyValuePair<Type, MethodInfo>> GetExtensionMethodsDefinedInType(this Type t){
    if (!t.IsSealed || t.IsGenericType || t.IsNested)
        return Enumerable.Empty<KeyValuePair<Type, MethodInfo>>();

    var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static)
                   .Where(m => m.IsDefined(typeof(ExtensionAttribute), false));

    List<KeyValuePair<Type, MethodInfo>> pairs = new List<KeyValuePair<Type, MethodInfo>>();
    foreach (var m in methods)
    {
        var parameters = m.GetParameters();
        if (parameters.Length > 0)
        {
            if (parameters[0].ParameterType.IsGenericParameter)
            {
                if (m.ContainsGenericParameters)
                {
                    var genericParameters = m.GetGenericArguments();
                    Type genericParam = genericParameters[parameters[0].ParameterType.GenericParameterPosition];
                    foreach (var constraint in genericParam.GetGenericParameterConstraints())
                        pairs.Add(new KeyValuePair<Type, MethodInfo>(parameters[0].ParameterType, m));
                }
            }
            else
                pairs.Add(new KeyValuePair<Type, MethodInfo>(parameters[0].ParameterType, m));
        }
    }

    return pairs;}

这只有一个问题:返回的类型与typeof(..)的预期不同,因为它是通用参数类型。为了找到给定类型的所有扩展方法,您必须比较Type的所有基类型和接口的GUID,如:

public List<MethodInfo> GetExtensionMethodsOf(Type t){
    List<MethodInfo> methods = new List<MethodInfo>();
    Type cur = t;
    while (cur != null)
    {

        TypeInfo tInfo;
        if (typeInfo.TryGetValue(cur.GUID, out tInfo))
            methods.AddRange(tInfo.ExtensionMethods);


        foreach (var iface in cur.GetInterfaces())
        {
            if (typeInfo.TryGetValue(iface.GUID, out tInfo))
                methods.AddRange(tInfo.ExtensionMethods);
        }

        cur = cur.BaseType;
    }
    return methods;}

完成:

我保留了一个类型信息对象的字典,我在迭代所有程序集的所有类型时构建:

private Dictionary<Guid, TypeInfo> typeInfo = new Dictionary<Guid, TypeInfo>();

其中TypeInfo定义为:

public class TypeInfo{
    public TypeInfo()
    {
        ExtensionMethods = new List<MethodInfo>();
    }

    public List<ConstructorInfo> Constructors { get; set; }

    public List<FieldInfo> Fields { get; set; }
    public List<PropertyInfo> Properties { get; set; }
    public List<MethodInfo> Methods { get; set; }

    public List<MethodInfo> ExtensionMethods { get; set; }}


查看完整回答
反对 回复 2019-08-12
  • 3 回答
  • 0 关注
  • 280 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信