识别扩展方法的思考

识别扩展方法的思考

在C#中是否有一种使用反射来确定方法是否已作为扩展方法添加到类的技术?

给定一个扩展方法,如下所示,可以确定Reverse()已被添加到字符串类?

public static class StringExtensions{
    public static string Reverse(this string value)
    {
        char[] cArray = value.ToCharArray();
        Array.Reverse(cArray);
        return new string(cArray);
    }}

我们正在寻找一种机制,在单元测试中确定扩展方法是由开发人员适当添加的。尝试这种情况的一个原因是,开发人员可能会在实际的类中添加类似的方法,如果是,编译器将选择该方法。


慕运维8079593
浏览 281回答 3
3回答

皈依舞

这将返回某种类型中定义的所有扩展方法的列表,包括通用类型:public&nbsp;static&nbsp;IEnumerable<KeyValuePair<Type,&nbsp;MethodInfo>>&nbsp;GetExtensionMethodsDefinedInType(this&nbsp;Type&nbsp;t){ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!t.IsSealed&nbsp;||&nbsp;t.IsGenericType&nbsp;||&nbsp;t.IsNested) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Enumerable.Empty<KeyValuePair<Type,&nbsp;MethodInfo>>(); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;methods&nbsp;=&nbsp;t.GetMethods(BindingFlags.Public&nbsp;|&nbsp;BindingFlags.Static) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Where(m&nbsp;=>&nbsp;m.IsDefined(typeof(ExtensionAttribute),&nbsp;false)); &nbsp;&nbsp;&nbsp;&nbsp;List<KeyValuePair<Type,&nbsp;MethodInfo>>&nbsp;pairs&nbsp;=&nbsp;new&nbsp;List<KeyValuePair<Type,&nbsp;MethodInfo>>(); &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;m&nbsp;in&nbsp;methods) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;parameters&nbsp;=&nbsp;m.GetParameters(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(parameters.Length&nbsp;>&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(parameters[0].ParameterType.IsGenericParameter) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(m.ContainsGenericParameters) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;genericParameters&nbsp;=&nbsp;m.GetGenericArguments(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;genericParam&nbsp;=&nbsp;genericParameters[parameters[0].ParameterType.GenericParameterPosition]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;constraint&nbsp;in&nbsp;genericParam.GetGenericParameterConstraints()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pairs.Add(new&nbsp;KeyValuePair<Type,&nbsp;MethodInfo>(parameters[0].ParameterType,&nbsp;m)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pairs.Add(new&nbsp;KeyValuePair<Type,&nbsp;MethodInfo>(parameters[0].ParameterType,&nbsp;m)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;pairs;}这只有一个问题:返回的类型与typeof(..)的预期不同,因为它是通用参数类型。为了找到给定类型的所有扩展方法,您必须比较Type的所有基类型和接口的GUID,如:public&nbsp;List<MethodInfo>&nbsp;GetExtensionMethodsOf(Type&nbsp;t){ &nbsp;&nbsp;&nbsp;&nbsp;List<MethodInfo>&nbsp;methods&nbsp;=&nbsp;new&nbsp;List<MethodInfo>(); &nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;cur&nbsp;=&nbsp;t; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(cur&nbsp;!=&nbsp;null) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TypeInfo&nbsp;tInfo; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeInfo.TryGetValue(cur.GUID,&nbsp;out&nbsp;tInfo)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods.AddRange(tInfo.ExtensionMethods); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(var&nbsp;iface&nbsp;in&nbsp;cur.GetInterfaces()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(typeInfo.TryGetValue(iface.GUID,&nbsp;out&nbsp;tInfo)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods.AddRange(tInfo.ExtensionMethods); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;cur.BaseType; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;methods;}完成:我保留了一个类型信息对象的字典,我在迭代所有程序集的所有类型时构建:private&nbsp;Dictionary<Guid,&nbsp;TypeInfo>&nbsp;typeInfo&nbsp;=&nbsp;new&nbsp;Dictionary<Guid,&nbsp;TypeInfo>();其中TypeInfo定义为:public&nbsp;class&nbsp;TypeInfo{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TypeInfo() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExtensionMethods&nbsp;=&nbsp;new&nbsp;List<MethodInfo>(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<ConstructorInfo>&nbsp;Constructors&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<FieldInfo>&nbsp;Fields&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<PropertyInfo>&nbsp;Properties&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<MethodInfo>&nbsp;Methods&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<MethodInfo>&nbsp;ExtensionMethods&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}}
打开App,查看更多内容
随时随地看视频慕课网APP