C#编写的程序会编译成一个程序集(.DLL或.exe),其中会包含元数据、编译代码和资源,通过反射可以获取到程序集中的信息
通俗来讲,反射就是我们在只知道一个对象的外部而不了解内部结构的情况下,可以知道这个对象的内部实现
反射:System.Reflection .Net框架提供的帮助类库,可以读取并使用metadata
很明显我们创建了一个Mysql的调用实例,并且使用了Query的方法
IDBHelper dBHelper = new MysqlHelper();
dBHelper.Query();
Assembly assembly = Assembly.Load("lyrics.db.Mysql"); // dll 名称 从当前目录加载
Type type = assembly.GetType("lyrics.db.Mysql.MysqlHelper");
object ohelper = Activator.CreateInstance(type);
IDBHelper dBHelper1 = (IDBHelper)ohelper;
dBHelper1.Query();
Assembly assembly = Assembly.Load("lyrics.db.Mysql"); // dll 名称 从当前目录加载
Assembly assembly1 = Assembly.LoadFile(@"D:\Demo\Demo\bin\Debug\lyrics.db.Mysql.dll"); // 完整路径加载,可以是别的目录
Assembly assembly2 = Assembly.LoadFrom("lyrics.db.Mysql.dll");
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<appSettings>
<add key="IDBHelperConfig" value="lyrics.db.Mysql,lyrics.db.Mysql.MysqlHelper"/>
</appSettings>
</configuration>
public class Factory
{
private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
private static string DllName = IDBHelperConfig.Split(',')[0];
private static string TypeName = IDBHelperConfig.Split(',')[1];
public static IDBHelper CreateHelper() {
Assembly assembly = Assembly.Load(DllName); // dll 名称 从当前目录加载
Type type = assembly.GetType(TypeName);
object ohelper = Activator.CreateInstance(type);
return (IDBHelper)ohelper;
}
}
这样我们就可以修改配置文件和对应目录下的dll来使用不同的数据库
Assembly assembly = Assembly.Load("lyrics.db.Mysql"); // dll 名称 从当前目录加载
Type type = assembly.GetType("lyrics.db.Mysql.MysqlHelper");
object ohelper = Activator.CreateInstance(type);
object ohelper2 = Activator.CreateInstance(type,true); // 第二个参数可以调用私有构造函数,可以破坏单例
object ohelper3= Activator.CreateInstance(type, new object[] { 123});// 调用含参的构造函数
Type type2 = assembly.GetType("lyrics.db.Mysql.MysqlHelper`3"); // 泛型获取类型使用`3代表此泛型类有三个泛型参数
var newType = type2.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });//指定三个泛型参数分别为int、string、DateTime
object ohelper4 = Activator.CreateInstance(newType);
var method = type.GetMethod("Query");
method.Invoke(ohelper, null);
var method2 = type.GetMethod("Query");
method.Invoke(ohelper, new object[] { 123 });
var method3 = type.GetMethod("Query");
method.Invoke(ohelper, new object[] { "asfhgiaksf" });
method.Invoke(null, new object[] { "asfhgiaksf" }); // 静态类型可以不传实例
var method4 = type.GetMethod("Query",new Type[] { }); //无参的重载方法
method.Invoke(ohelper, new object[] { });
var method5 = type.GetMethod("Query", BindingFlags.Instance| BindingFlags.NonPublic);
method.Invoke(ohelper, new object[] { });
Type type1 = assembly.GetType("lyrics.db.Mysql.MysqlHelper`1"); // 代表lyrics.db.Mysql.MysqlHelper这个类只有一个泛型参数
Type type2 = type1.MakeGenericType(new Type[] { typeof(int)});// 设置lyrics.db.Mysql.MysqlHelper这个泛型类的具体类型为 int
object obj = Activator.CreateInstance(type2); // 创造对应的实例
MethodInfo methodInfo = type2.GetMethod("Query"); // 获取其中的函数
MethodInfo methodInfo1 = methodInfo.MakeGenericMethod(new Type[] { typeof(string),typeof(DateTime)});//设置参数类型为string、dateTime
methodInfo1.Invoke(obj, new object[] {123,"safas",DateTime.Now });// 掉用方法
People people = new People() { Id = 123, Name = "ly", Description = "saffasf" };
Type type = typeof(People);
object oPeople= Activator.CreateInstance(type);
foreach (var prop in type.GetProperties()) {
Console.WriteLine(prop.Name);
Console.WriteLine(prop.GetValue(oPeople));
if (prop.Name.Equals("Id")) {
prop.SetValue(oPeople, 234);
}
Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}");
}
字段与属性类似
动态