反射
一、课前准备
现在有三个类,分别是:
-
接口
interface DBHelper
{
void AddRecord(int i);
}
-
实现接口类1 MySqlDb
class MySqlDb : DBHelper
{
public void AddRecord(int i)
{
Console.WriteLine("这里使用的是MySql数据库新增一条记录");
}
}
-
实现接口类2 SqlServerDB
class SqlServerDB : DBHelper
{
public void AddRecord(int i)
{
Console.WriteLine("这里使用的是SqlServer数据库新增一条记录");
}
}
二、反射引入
-
普通定义并使用对象
DBHelper hhDB = new MySqlDb();
hhDB.AddRecord();
-
利用反射定义并使用对象方法1:通过程序集名称
Assembly assembly = Assembly.Load("hh反射");//获取程序集名称,它会把这个程序集下所有的相关信息存到assembly对象中,如属性存到对象下的CustomAttributes,类存到对象下的DefinedTypes
Type type = assembly.GetType("hh反射.MySqlDb");//获取命名空间下的类
dynamic oDB = Activator.CreateInstance(type);//创建获得类的对象
MethodInfo method = type.GetMethod("AddRecord");//获得类下的方法
method.Invoke(oDB, new Object[] {1}); //调用方法
-
-
其中程序集名称是:
-
-
利用反射定义并使用对象方法2:通过dll路径/exe路径
Assembly assembly = Assembly.LoadFile("F:\\学习盘\\hh反射\\bin\\Debug\\hh反射.exe");//它会把这个程序集下所有的相关信息存到assembly对象中,如属性存到对象下的CustomAttributes,类存到对象下的DefinedTypes
Type type = assembly.GetType("hh反射.MySqlDb");//获取命名空间下的类
dynamic oDB = Activator.CreateInstance(type);//创建获得类的对象
MethodInfo method = type.GetMethod("AddRecord");//获得类下的方法
method.Invoke(oDB, new Object[] {1}); //调用方法
-
利用反射定义并使用对象方法3:由已定义对象获得
DBHelper hhDB = new MySqlDb();
hhDB.AddRecord(2);
Type type = hhDB.GetType();
dynamic oDB = Activator.CreateInstance(type);//创建获得类的对象
MethodInfo method = type.GetMethod("AddRecord");//获得类下的方法
method.Invoke(oDB, new Object[] {1}); //调用方法
- 反射构造函数
Dim DllPath As String = My.Application.Info.DirectoryPath & "\Oracle.ManagedDataAccess.dll" If IO.File.Exists(DllPath) = False Then MsgBox("Oracle.ManagedDataAccess.dll 不存在!") End If Dim OracleConType As Assembly = Assembly.LoadFile(DllPath) Dim mtype As Type = OracleConType.GetType("Oracle.ManagedDataAccess.Client.OracleConnection") Dim hhOracleCon As Object = Activator.CreateInstance(mtype) Dim OracleCmdType As Type = OracleConType.GetType("Oracle.ManagedDataAccess.Client.OracleCommand") Dim OracleCMD As Object = hhOracleCon.CreateCommand '获取所有构造函数 Dim constructors As ConstructorInfo() = OracleCmdType.GetConstructors() '遍历所有构造函数 For Each item As ConstructorInfo In constructors Dim paramsInfos As ParameterInfo() = item.GetParameters() '获取构造函数的参数信息 If paramsInfos.Length = 2 Then '取得只有两个参数的构造函数 Dim o As List(Of Object) = New List(Of Object)() From {"1", hhOracleCon} OracleCMD = constructors(2).Invoke(o.ToArray()) '传入参数调用构造函数 End If Next OracleCMD.ExecuteNonQuery()
-
三、反射基本应用
接口:DBHelper
实现类1:MySqlDb
实现类2:SqlServerDB
上述的三个类,MySqlDb和SqlServerDB都是继承与接口DBHelper,即实现类不直接依赖细节而是依赖抽象(接口),即下面使用的对象都是定义为抽象(接口)DBHelper类型的,这样的好处就是只要抽象(接口)不变,我上层的代码就不需要改变。假如实际项目中需要把数据库MySqlDb改为SqlServerDB数据库可以通过下面实现:
-
假如项目中本来是应用MySqlDb
DBHelper hhDB = new MySqlDb();
hhDB.AddRecord();
-
现改为SqlServerDB
DBHelper hhDB = new SqlServerDB ();
hhDB.AddRecord();
-
上面只对New后的类型修改即可,仍然是需要修改代码,假如项目中一开始就是利用反射来调用数据库。那么需要这样修改:
-
反射调用时本来是应用MySqlDb
Assembly assembly = Assembly.Load("hh反射");//获取程序集名称,它会把这个程序集下所有的相关信息存到assembly对象中,如属性存到对象下的CustomAttributes,类存到对象下的DefinedTypes
Type type = assembly.GetType("hh反射.MySqlDb");
dynamic oDB = Activator.CreateInstance(type);//创建获得类的对象
MethodInfo method = type.GetMethod("AddRecord");//获得类下的方法
method.Invoke(oDB, new Object[] {1}); //调用方法
-
反射调用时现改为SqlServerDB
Assembly assembly = Assembly.Load("hh反射");//获取程序集名称,它会把这个程序集下所有的相关信息存到assembly对象中,如属性存到对象下的CustomAttributes,类存到对象下的DefinedTypes
Type type = assembly.GetType("hh反射.SqlServerDB");
dynamic oDB = Activator.CreateInstance(type);//创建获得类的对象
MethodInfo method = type.GetMethod("AddRecord");//获得类下的方法
method.Invoke(oDB, new Object[] {1}); //调用方法
-
从上面的代码可以看出,假如全程是用反射来做的话,更换数据库只需要把字符串"hh反射.MySqlDb"变更为"hh反射.SqlServerDB"所以反射可以提供一种不需要修改代码,仅需修改某些配置文件(字符串)就可以改变程序逻辑的功能