C#--反射基础
以下是学习笔记:
一,反射的基本信息

DLL/EXE: 主要区别EXE文件有一个入口,DLL文件不能运行,但是DLL能拿到其他地方去使用
metadata(元数据):描述exe/dll文件的一个清单,记录了exe/dll文件中有哪些类,属性,特性,字段。。。
Reflection(反射):用来操作或获取元数据metadata
有什么作用:
1,更新程序(更新自己的DLL)
一个工程有多个项目,更新其中一个小项目,就是替换一个dll文件就可以了
2,使用别人的DLL文件(这种可以读取别人的私有的东西)
反射是什么:就是一个操作metadata的一个类库(可以把反射当成一个小工具,用来读取或操作元数据的)
使用场景:asp.net MVC ,ORM,LOC,AOP,几乎所有的框架都会使用反射
二,通过反射加载DLL文件
代码:
//加载方式一,dll文件名(当前目录)
//Assembly assembly=Assembly.Load("Ant.DB.SQLServer");
//加载方式二,dll文件的完整路径(文件具体路径)
//Assembly assembly=Assembly.LoadFile(@"E:\VS workspace\学习 单个项目\反射\MyReflection\Ant.DB.SQLServer\bin\Debug\Ant.DB.SQLServer.dll");
//加载方式三,dll文件的完全限定名(当期目录)
//Assembly assembly=Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//加载方式四,跟上面是一样的,只是参数不一样(文件具体路径)
Assembly assembly =Assembly.LoadFrom(@"E:\VS workspace\学习 单个项目\反射\MyReflection\Ant.DB.SQLServer\bin\Debug\Ant.DB.SQLServer.dll");
//注意:方式一的文件是当前目录的,因为在引用里面添加了项目的。
// 如果第三方的需要复制到项目里面,或者用文件具体路径
foreach (var type in assembly.GetTypes())//找所有类型
{
Console.WriteLine(type.Name);
foreach (var method in type.GetMethods())//找所有方法
{
Console.WriteLine("这是:"+method.Name+" 方法");
}
}
注意:

三,通过反射创建对象
1,使用反射创建对象(无参数的构造函数)
//【1】加载DLL文件
Assembly assembly2 =Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
//Type type2 = assembly2.GetType("MySQLServerHelper");//只写一个类名是不行的
Type type2 = assembly2.GetType("Ant.DB.SQLServer.MySQLServerHelper");//需要 命名空间.类名
//【3】创建对象
object oDbHelper = Activator.CreateInstance(type2);
//上面等同于 MySQLServerHelper mySqlServerHelper=new MySQLServerHelper();
IDBHelper dBHelper=oDbHelper as IDBHelper;//类型转换(as转换不报错,类型不对就返回null)
//IDBHelper dBHelper2 =(IDBHelper)oDbHelper;//不用as转换,类型不对就报错
//【4】调用对象的方法
dBHelper.Query();
2,使用反射创建对象(带参数的构造函数)
//【1】加载DLL文件
Assembly assembly3 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type3 = assembly3.GetType("Ant.DB.SQLServer.ReflectionTest");//需要 命名空间.类型名称
//获取到这个类型下面的所有构造方法
foreach (ConstructorInfo ctor in type3.GetConstructors())//获取所有的构造方法
{
Console.WriteLine(ctor.Name);
foreach (var parameter in ctor.GetParameters())//获取构造方法的所有参数类型
{
Console.WriteLine(parameter.ParameterType);//显示类型名称
}
}
//【3】创建对象
object oDbHelper3_1 = Activator.CreateInstance(type3);//无参数的构造函数
object oDbHelper3_2 = Activator.CreateInstance(type3,new object[]{"Ant 编程"});//有1个参数的构造函数
object oDbHelper3_3 = Activator.CreateInstance(type3,new object[]{123});//有1个参数的构造函数
object oDbHelper3_4 = Activator.CreateInstance(type3,new object[]{123,"Ant 编程"});//有2不同类型的参数的构造函数
结果:

3,使用反射创建对象(私有的构造函数)
Console.WriteLine("---------------------------UseReflection 使用反射创建对象(私有的构造函数)-------------------------");
//PrivateCtor privateCtor=new PrivateCtor();//私有构造函数,这样创建直接报错的
//【1】加载DLL文件
Assembly assembly4 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type4 = assembly4.GetType("Ant.DB.SQLServer.PrivateCtor");//需要 命名空间.类型名称
//【3】创建对象
object oPrivate = Activator.CreateInstance(type4, true);//需要参数2,true,就可以创建私有构造函数的对象啦
//这个功能 还用在我们的单例模式里面(一个对象只能创建一次) 。这个也叫反射破坏单例模式。
四,通过反射创建创建泛型类
1,使用反射创建泛型类
泛型类:
namespace Ant.DB.SQLServer
{
/// <summary>
/// 泛型类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="S"></typeparam>
public class GenericClass<T,W,S>
{
}
}
Console.WriteLine("---------------------------UseReflection 使用反射创建泛型类-------------------------");
//【1】加载DLL文件
Assembly assembly5 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
//Type type5 = assembly5.GetType("Ant.DB.SQLServer.GenericClass");//需要 命名空间.类型名称
Type type5 = assembly5.GetType("Ant.DB.SQLServer.GenericClass`3");//反单引号+参数的个数(3就是3个泛型类型的参数个数)
//把参数类型给上面的type5
Type makType= type5.MakeGenericType(new Type[] {typeof(int), typeof(string), typeof(double)});//typeof(int)获取到类型的具体类型
//【3】创建泛型类的对象
object oGeneric = Activator.CreateInstance(makType);
使用反射创建泛型类的注意事项:

五,通过反射调用方法
1,类的方法代码:
namespace Ant.DB.SQLServer
{
class ReflectionTest
{
public ReflectionTest()
{
Console.WriteLine($"这是{this.GetType()}无参数的构造函数");
}
public ReflectionTest(string name)
{
Console.WriteLine($"这是{this.GetType()}有参数的构造函数,类型为{name.GetType()}");
}
public ReflectionTest(int id)
{
Console.WriteLine($"这是{this.GetType()}有参数的构造函数,类型为{id.GetType()}");
}
public ReflectionTest(int id,string name)
{
Console.WriteLine($"这是{this.GetType()}有参数的构造函数,类型为{id.GetType()}和{name.GetType()}");
}
public void Test1()
{
Console.WriteLine($"这里是{this.GetType()}的Test1");
}
public void Test2(int id)
{
Console.WriteLine($"这里是{this.GetType()}的Test2");
}
public void Test3(int id,string name)
{
Console.WriteLine($"这里是{this.GetType()}的Test3-1");
}
public void Test3(string name, int id)
{
Console.WriteLine($"这里是{this.GetType()}的Test3-2");
}
public void Test3( int id)
{
Console.WriteLine($"这里是{this.GetType()}的Test3-3");
}
public void Test3(string name)
{
Console.WriteLine($"这里是{this.GetType()}的Test3-4");
}
public void Test3()
{
Console.WriteLine($"这里是{this.GetType()}的Test3-5");
}
//私有方法
private void Test4(string name)
{
Console.WriteLine($"这里是{this.GetType()}的Test4的私有方法");
}
//静态方法
public static void Test5(string name)
{
Console.WriteLine($"这里是{typeof(ReflectionTest)}的Test5的静态方法");
}
}
}
2,使用反射调用方法:
Console.WriteLine("---------------------------UseReflection 使用反射调用方法-------------------------");
//【1】加载DLL文件
Assembly assembly6 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type6 = assembly6.GetType("Ant.DB.SQLServer.ReflectionTest");//需要 命名空间.类型名称
//【3】创建对象
object oReflection = Activator.CreateInstance(type6);//无参数的构造函数
//获取类型的所有方法和参数
foreach (var method in type6.GetMethods())
{
Console.WriteLine("方法:"+method.Name);
foreach (var parameters in method.GetParameters())
{
Console.WriteLine("参数名:"+parameters.Name+",参数类型:"+parameters.ParameterType);
}
}
{
//【4】获取方法
//1,通过方法名来调用方法
MethodInfo methodInfo = type6.GetMethod("Test1");
//【5】调用无参数的方法
methodInfo.Invoke(oReflection, null);
}
{
MethodInfo methodInfo = type6.GetMethod("Test2");
//调用带参数的方法
methodInfo.Invoke(oReflection, new Object[]{123456});
}
{
//带参数的重载方法
MethodInfo methodInfo = type6.GetMethod("Test3",new Type[]{typeof(int),typeof(string)});//重载方法注意:指定参数类型
methodInfo.Invoke(oReflection, new Object[] { 123456,"jason" });//传入参数类型
}
{
MethodInfo methodInfo = type6.GetMethod("Test3", new Type[] { typeof(string), typeof(int) });
methodInfo.Invoke(oReflection, new Object[] { "jason" ,123456});
}
{
MethodInfo methodInfo = type6.GetMethod("Test3", new Type[] { typeof(int) });
methodInfo.Invoke(oReflection, new Object[] { 123456 });
}
{
MethodInfo methodInfo = type6.GetMethod("Test3", new Type[] { typeof(string) });
methodInfo.Invoke(oReflection, new Object[] { "jason"});
}
{
//无参数的重载方法
MethodInfo methodInfo = type6.GetMethod("Test3", new Type[] {});
methodInfo.Invoke(oReflection, null);
}
{
//静态方法的调用方式1
MethodInfo methodInfo = type6.GetMethod("Test5");
methodInfo.Invoke(oReflection, new object[]{"jason"});
}
{
//静态方法的调用方式2
MethodInfo methodInfo = type6.GetMethod("Test5");
methodInfo.Invoke(null, new object[] { "jason" });//静态方法,对象可以为空
}
结果:

3,通过反射调用私有方法
Console.WriteLine("---------------------------UseReflection 使用反射调用私有方法-------------------------");
//【1】加载DLL文件
Assembly assembly7 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type7 = assembly7.GetType("Ant.DB.SQLServer.ReflectionTest");//需要 命名空间.类型名称
//【3】创建对象
object oReflection7 = Activator.CreateInstance(type7);//无参数的构造函数
{
//【4】获取私有方法
//1,通过方法名来调用方法
//MethodInfo methodInfo = type6.GetMethod("Test4");//私有方法,直接给一个方法名还是不行的
MethodInfo methodInfo = type6.GetMethod("Test4",BindingFlags.Instance|BindingFlags.NonPublic);//获取私有方法需要,参数2:备注,一个说明,指定是一个实例,说明是非公开的
//【5】调用带参数的私有方法
methodInfo.Invoke(oReflection7, new object[]{"json"});
}
4,使用反射调用泛型方法(普通类里面的泛型方法调用)
泛型类和泛型方法的示例代码:
namespace Ant.DB.SQLServer
{
/// <summary>
/// 泛型类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="S"></typeparam>
public class GenericClass<T,W,S>
{
/// <summary>
/// 泛型方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="t"></param>
/// <param name="w"></param>
/// <param name="s"></param>
public void Test<T,W,S>(T t, W w, S s)
{
Console.WriteLine($"第一个类型是={t.GetType().Name},第二个类型是={w.GetType().Name},第三个类型是={s.GetType().Name},");
}
}
/// <summary>
/// 普通的类
/// </summary>
public class GenericMethod
{
/// <summary>
/// 泛型方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="W"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="t"></param>
/// <param name="w"></param>
/// <param name="s"></param>
public void Test<T,W,S>(T t, W w, S s)
{
Console.WriteLine($"第一个类型是={t.GetType().Name},第二个类型是={w.GetType().Name},第三个类型是={s.GetType().Name},");
}
}
}
Console.WriteLine("---------------------------UseReflection 使用反射调用泛型方法(普通类里面的泛型方法调用)-------------------------");
//【1】加载DLL文件
Assembly assembly8 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type8 = assembly8.GetType("Ant.DB.SQLServer.GenericMethod");//需要 命名空间.类型名称
//【3】创建对象
object oReflection8 = Activator.CreateInstance(type8);//实例化类型
//【4】通过方法名找到方法
MethodInfo methodInfo8 = type8.GetMethod("Test");
//【5】确定方法的参数类型和个数
var methodGeneric = methodInfo8.MakeGenericMethod(new Type[] { typeof(int),typeof(string),typeof(DateTime)});
//【6】调用方法
methodGeneric.Invoke(oReflection8, new object[] {123456, "jason", DateTime.Now});
5,使用反射调用泛型方法(泛型类里面的泛型方法调用)
Console.WriteLine("---------------------------UseReflection 使用反射调用泛型方法(泛型类里面的泛型方法调用)-------------------------");
//【1】加载DLL文件
Assembly assembly9 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
//Type type9 = assembly9.GetType("Ant.DB.SQLServer.GenericClass");//需要 命名空间.类型名称,这个普通的方法不能获取泛型类型的
Type type9 = assembly9.GetType("Ant.DB.SQLServer.GenericClass`3");//注意:泛型类需要: 反单引号+参数个数
//【3】确定泛型方法的参数类型
Type typeNew9 = type9.MakeGenericType(new Type[] {typeof(int), typeof(string), typeof(DateTime)});
//【4】创建对象
//object oReflection9 = Activator.CreateInstance(type9);//实例化类型
object oReflection9 = Activator.CreateInstance(typeNew9);//实例化类型,需要用新的这个typeNew9
//【5】通过方法名找到方法
MethodInfo methodInfo9 = typeNew9.GetMethod("Test");//需要用新的这个typeNew9
//【6】确定方法的参数类型和个数
var methodGeneric9 = methodInfo9.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
//【7】调用方法
methodGeneric9.Invoke(oReflection9, new object[] { 123456, "jason", DateTime.Now });
六,使用反射操作字段和属性等成员
要操作的Studnet类的成员
namespace Ant.DB.SQLServer
{
public class Student
{
public int Id { get; set; }
public string StudentName { get; set; }
public string StudentAddress { get; set; }
public int age;
public void Test()
{
}
}
}
Console.WriteLine("---------------------------UseReflection 使用反射操作字段和属性等成员-------------------------");
Student student = new Student()
{
Id = 1,
StudentAddress = "杭州",
StudentName = "jason"
};
//【1】加载DLL文件
Assembly assembly10 = Assembly.LoadFrom("Ant.DB.SQLServer.dll");
//【2】DLL文件中有很多类型,获取类型(要完整的类型名称)
Type type10 = assembly10.GetType("Ant.DB.SQLServer.Student"); //需要 命名空间.类型名称,这个普通的方法不能获取泛型类型的
//【3】创建对象
object oReflection10 = Activator.CreateInstance(type10); //实例化类型
//方式一:获取和设置属性
foreach (var prop in type10.GetProperties())
{
Console.WriteLine($"类型:{prop.PropertyType},属性名称:{prop.Name},值:{prop.GetValue(student)}");//注意,这个student是上面的new出来的那个
Console.WriteLine("---------------------------------------");
if (prop.Name.Equals("Id"))
{
prop.SetValue(student, 2);
}
if (prop.Name.Equals("StudentAddress"))
{
prop.SetValue(student, "杭州2");
}
if (prop.Name.Equals("StudentName"))
{
prop.SetValue(student, "jason2");
}
Console.WriteLine($"类型:{prop.PropertyType},属性名称:{prop.Name},值:{prop.GetValue(student)}");
}
//方式二:获取和设置属性
MemberInfo[] memberInfos=type10.GetMembers();//所有的成员信息,包括属性,字段,方法
PropertyInfo[] propertyInfos = type10.GetProperties();//查找所有的属性
PropertyInfo propertyInfo = type10.GetProperty("Id");//根据名称找到属性
结果:

7,反射调用方法的案例
【7.1】带返回值的
https://blog.csdn.net/ftell/article/details/81745908?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=2
public class MyClass
{
public string func1()
{
return "func1";
}
public string func2()
{
return "func2";
}
public string func3()
{
return "func3";
}
public string func4()
{
return "func4";
}
public void callFunc(string funcName)
{
MethodInfo method = GetType().GetMethod(funcName);
Func<string> func = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), this, method);
Console.Write(func() + " ");
}
}
【7.2】带参数的,不带返回值的
public void SetOut_0()
{
btnCh8_Click(null, null);
}
public void SetOut_1()
{
btnCh9_Click(null, null);
}
public void SetOut_2()
{
btnCh10_Click(null, null);
}
public void SetOut_3()
{
btnCh11_Click(null, null);
}
public void SetOut_4()
{
btnCh12_Click(null, null);
}
public void SetOut_5()
{
btnCh13_Click(null, null);
}
public void SetOut_6()
{
btnCh14_Click(null, null);
}
public void SetOut(string methodName)
{
MethodInfo method = GetType().GetMethod(methodName);
method.Invoke(this, null);
}

浙公网安备 33010602011771号