反射调用扩展或泛型方法
扩展方法调用:
我们可以把外部扩展方法理解为一个特定静态类,虽然在IDE中,扩展方法能被参数对象直接调用,实际上它本质的方法地址还是存储在外部扩展类上。因此,如果你想通过被继承的类去获取扩展方法名称是获取不到的。
public class TestA
{
public string Name { get; set; }
}
public static class TestAExt
{
public static void Set(this TestA obj,string txt)
{
obj.Name = txt;
}
}
直接在对象中调用扩展方法:
void test2()
{
TestA t = new TestA() { Name = "BBBBBB" };
t.Set("CCCCC");
}
如上代码,如果你想从中typeof(TestA).GetMethods是无法获得Set方法的。
只能通过typeof(TestAExt).GetMethods获得,并发射调用。
示例:
static void test2()
{
TestA t = new TestA() { Name = "BBBBBB" };
//t.Set("CCCCC");
var mt= typeof(TestAExt).GetMethod("Set");
mt.Invoke(t, new object[] { t, "CCCCC" });
Console.WriteLine(t.Name);
}
泛型方法的调用,需要遵循以下操作:
新增一个TestB类,建立泛型方法:
public static class TestB
{
public static string Get<T>(T obj)
{
if (obj is TestA a)
{
return a.Name;
}
return null;
}
}
反射调用示例:
static void test3()
{
TestA t = new TestA() { Name = "ZZZZZ" };
var mt = typeof(TestB).GetMethod("Get");
var mt2 = mt.MakeGenericMethod(typeof(TestA));
Console.WriteLine(mt2.Invoke(null, new object[] { t }));
}
扩展泛型的反射调用
参考如下:
static void test0()
{
met = type.GetMethod("XXX");
var met2 = met.MakeGenericMethod(parm[0].GetType());
return met2.Invoke(null, parm);
}
泛型获取参数类:
GenericTypeArguments
比如,获取DbContext中的所有参数类:
DbContext.GetType().GetProperties().Where(q => q.PropertyType.IsGenericType && typeof(System.Data.Entity.DbSet<>).IsAssignableFrom(q.PropertyType.GetGenericTypeDefinition()))
static void Main(string[] args) { foreach (PropertyInfo pi in typeof(ClassLibrary2.Model2).GetProperties().Where(q => q.PropertyType.IsGenericType && typeof(System.Data.Entity.DbSet<>).IsAssignableFrom(q.PropertyType.GetGenericTypeDefinition()))) { Console.WriteLine($"FullName:{pi.PropertyType.FullName}"); Console.WriteLine($"GetGenericTypeDefinition:{pi.PropertyType.GetGenericTypeDefinition()}"); Console.WriteLine($"IsConstructedGenericType:{pi.PropertyType.IsConstructedGenericType}"); Console.WriteLine($"IsGenericParameter:{pi.PropertyType.IsGenericParameter}"); Console.WriteLine($"IsGenericType:{pi.PropertyType.IsGenericType}"); Console.WriteLine($"IsGenericTypeDefinition:{pi.PropertyType.IsGenericTypeDefinition}"); Console.WriteLine($"=============GenericTypeArguments============="); foreach (Type type in pi.PropertyType.GenericTypeArguments) { Console.WriteLine($"{type.FullName}"); } if (pi.PropertyType.IsGenericParameter) { Console.WriteLine($"=============GetGenericParameterConstraints============="); foreach (Type type in pi.PropertyType.GetGenericParameterConstraints()) { Console.WriteLine($"{type.FullName}"); } } } Console.ReadLine(); }
FullName:System.Data.Entity.DbSet`1[[ClassLibrary2.MyEntity20, ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] GetGenericTypeDefinition:System.Data.Entity.DbSet`1[TEntity] IsConstructedGenericType:True IsGenericParameter:False IsGenericType:True IsGenericTypeDefinition:False =============GenericTypeArguments============= ClassLibrary2.MyEntity20 FullName:System.Data.Entity.DbSet`1[[ClassLibrary2.MyEntity21, ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] GetGenericTypeDefinition:System.Data.Entity.DbSet`1[TEntity] IsConstructedGenericType:True IsGenericParameter:False IsGenericType:True IsGenericTypeDefinition:False =============GenericTypeArguments============= ClassLibrary2.MyEntity21 FullName:System.Data.Entity.DbSet`1[[ClassLibrary2.MyEntity22, ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] GetGenericTypeDefinition:System.Data.Entity.DbSet`1[TEntity] IsConstructedGenericType:True IsGenericParameter:False IsGenericType:True IsGenericTypeDefinition:False =============GenericTypeArguments============= ClassLibrary2.MyEntity22 FullName:System.Data.Entity.DbSet`1[[ClassLibrary2.MyEntity23, ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] GetGenericTypeDefinition:System.Data.Entity.DbSet`1[TEntity] IsConstructedGenericType:True IsGenericParameter:False IsGenericType:True IsGenericTypeDefinition:False =============GenericTypeArguments============= ClassLibrary2.MyEntity23