簡體   English   中英

如何用反射調用泛型擴展方法?

[英]How to call a generic extension method with reflection?

我寫了擴展方法GenericExtension 現在我想調用擴展方法Extension methodInfo的值始終為null。

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));
    }
}

怎么了?

擴展方法沒有附加到Form類型,它附加到MyClass類型,所以抓住它的類型:

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

如果您有類似的擴展方法

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);
    }
}

基於@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運算符,如果在重構期間刪除了方法或類,則可以在運行時防止異常。

您傳入的字符串是您方法的通用參數。

但是你的約束說T需要從Form繼承(String不是)。

我假設你想寫typeof(MyForm)或其他一些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM