How to call a generic extension method with reflection?

后端 未结 4 1693
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-06 17:30

I wrote the extension method GenericExtension. Now I want to call the extension method Extension. But the value of methodInfo is alway

相关标签:
4条回答
  • 2020-12-06 17:56

    In case you have an extension method like

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

    you can invoke it (e. g. in tests) like so:

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-06 18:07

    You are passing in string as the generic parameter for your method..

    But your constraints say that T needs to inherit from Form (which String does not).

    I am assuming you wanted to write typeof(MyForm) or some such there instead.

    0 讨论(0)
  • 2020-12-06 18:12

    Building off of @Mike Perrenoud's answer, the generic method I needed to invoke was not constrained to the same type as the class of the extension method (i.e. T is not of type Form).

    Given the extension method:

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

    I used the following code to execute the method:

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

    where the types defined in _trackChangesOnTables are only known at runtime. By using the nameof operator, this protects against exceptions at runtime if the method or class is ever removed during refactoring.

    0 讨论(0)
  • 2020-12-06 18:18

    The extension method isn't attached to the type Form, it's attached to the type MyClass, so grab it off that type:

    MethodInfo methodInfo = typeof(MyClass).GetMethod("GenericExtension",
        new[] { typeof(Form), typeof(string) });
    
    0 讨论(0)
提交回复
热议问题