【问题标题】:How to call a generic extension method with reflection?如何使用反射调用通用扩展方法?
【发布时间】:2013-04-10 13:19:42
【问题描述】:

我写了扩展方法GenericExtension。现在我想调用扩展方法Extension。但methodInfo 的值始终为空。

public static class MyClass
{
    public static void GenericExtension<T>(this Form a, string b) where T : Form
    {
        // code...
    }

    public static void Extension(this Form a, string b, Type c)
    {
        MethodInfo methodInfo = typeof(Form).GetMethod("GenericExtension", new[] { typeof(string) });
        MethodInfo methodInfoGeneric = methodInfo.MakeGenericMethod(new[] { c });
        methodInfoGeneric.Invoke(a, new object[] { a, b });
    }

    private static void Main(string[] args)
    {
        new Form().Extension("", typeof (int));
    }
}

怎么了?

【问题讨论】:

标签: c# generics extension-methods methodinfo


【解决方案1】:

扩展方法没有附加到类型Form,它附加到类型MyClass,所以从那个类型中获取它:

MethodInfo methodInfo = typeof(MyClass).GetMethod("GenericExtension",
    new[] { typeof(Form), typeof(string) });

【讨论】:

  • 现在我很郁闷...解决方案如此简单明了谢谢
  • @David,别担心,您只是感到困惑,因为它感觉像扩展方法附加到类型Form。你只需要第二双眼睛。
  • 这将如何工作?扩展方法无法通过 GetMethod 方法检索...
【解决方案2】:

如果您有类似的扩展方法

public static class StringExtensions
{
    public static bool IsValidType<T>(this string value);
}

您可以像这样调用它(例如在测试中):

public class StringExtensionTests
{
    [Theory]
    [InlineData("Text", typeof(string), true)]
    [InlineData("", typeof(string), true)]
    [InlineData("Text", typeof(int), false)]
    [InlineData("128", typeof(int), true)]
    [InlineData("0", typeof(int), true)]
    public void ShouldCheckIsValidType(string value, Type type, bool expectedResult)
    {
        var methodInfo = 
            typeof(StringExtensions).GetMethod(nameof(StringExtensions.IsValidType),
            new[] { typeof(string) });
        var genericMethod = methodInfo.MakeGenericMethod(type);
        var result = genericMethod.Invoke(null, new[] { value });
        result.Should().Be(expectedResult);
    }
}

【讨论】:

    【解决方案3】:

    根据@Mike Perrenoud 的回答,我需要调用的泛型方法不限于与扩展方法的类相同的类型(即T 不是Form 类型)。

    给定扩展方法:

    public static class SqlExpressionExtensions
    {
        public static string Table<T>(this IOrmLiteDialectProvider dialect)
    }
    

    我使用以下代码来执行该方法:

    private IEnumerable<string> GetTrackedTableNames(IOrmLiteDialectProvider dialectProvider)
    {
        var method = typeof(SqlExpressionExtensions).GetMethod(nameof(SqlExpressionExtensions.Table), new[] { typeof(IOrmLiteDialectProvider) });
    
        if (method == null)
        {
            throw new MissingMethodException(nameof(SqlExpressionExtensions), nameof(SqlExpressionExtensions.Table));
        }
    
        foreach (var table in _trackChangesOnTables)
        {
            if (method.MakeGenericMethod(table).Invoke(null, new object[] { dialectProvider }) is string tableName)
            {
                yield return tableName;
            }
        }
    }
    

    _trackChangesOnTables 中定义的类型仅在运行时已知。通过使用nameof 运算符,如果在重构期间删除了方法或类,这可以防止运行时出现异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      相关资源
      最近更新 更多