一尘不染

反思以识别扩展方法

c#

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

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

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

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


阅读 201

收藏
2020-05-19

共1个答案

一尘不染

您必须查看所有可能定义扩展方法的程序集。

查找装饰ExtensionAttribute有的类,然后查找该类中
装饰有的方法ExtensionAttribute。然后检查第一个参数的类型,以查看它是否与您感兴趣的类型匹配。

这是一些完整的代码。可能更严格(它不是检查类型是否嵌套,或者没有至少一个参数),但它应该给您帮助。

using System;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;

public static class FirstExtensions
{
    public static void Foo(this string x) {}
    public static void Bar(string x) {} // Not an ext. method
    public static void Baz(this int x) {} // Not on string
}

public static class SecondExtensions
{
    public static void Quux(this string x) {}
}

public class Test
{
    static void Main()
    {
        Assembly thisAssembly = typeof(Test).Assembly;
        foreach (MethodInfo method in GetExtensionMethods(thisAssembly,
            typeof(string)))
        {
            Console.WriteLine(method);
        }
    }

    static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,
        Type extendedType)
    {
        var query = from type in assembly.GetTypes()
                    where type.IsSealed && !type.IsGenericType && !type.IsNested
                    from method in type.GetMethods(BindingFlags.Static
                        | BindingFlags.Public | BindingFlags.NonPublic)
                    where method.IsDefined(typeof(ExtensionAttribute), false)
                    where method.GetParameters()[0].ParameterType == extendedType
                    select method;
        return query;
    }
}
2020-05-19