问题
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?
回答1:
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) });
回答2:
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);
}
}
回答3:
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.
回答4:
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.
来源:https://stackoverflow.com/questions/15927028/how-to-call-a-generic-extension-method-with-reflection