I wrote the extension method GenericExtension
. Now I want to call the extension method Extension
. But the value of methodInfo
is always 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));
}
}
Whats wrong?
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) });
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);
}
}
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.
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.