1、反射加载实体类、实例方法
2、反射实现工厂可配置类
3、反射调用泛型类、泛型方法
4、反射使用类字段和类属性
提示:以下是本篇文章正文内容,下面案例可供参考
反射结合.Net编译器第一次编译生成的文件Metadata文件,加载其中的类、字段、方法信息,不直接使用类名而实例化类和使用类、类成员的一种手段。
该手段提供一定的方便:动态
也会有一定的缺点:1、写起来繁琐
2、避开编译器的检查,不会有语法错误提示,可以通过一定手段访问类的私有成员
3、 性能问题,这个影响其实网上说的特别多,但是实际的使用其实可以忽略,比如MVC使用的反射通过路由找到对应到控制器和调用的方法成员。EF也通过反射实现。通常第一次加载慢,后面会很快.
代码如下(示例):
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer"); //加载程序集,可以是dll或者.exe
Type type = assembly.GetType("Ruanmou.DB.SqlServer.Singleton");//获得类名的类型
Singleton singleton4 = (Singleton)Activator.CreateInstance(type, true);//新实例
Singleton singleton5 = (Singleton)Activator.CreateInstance(type, true);//新实例
Singleton singleton6 = (Singleton)Activator.CreateInstance(type, true);//新实例
反射实现工厂可配置的类,是通过在配置文件里面,写好要创建类实例的dll名、类名,然后通过通过工厂类读取配置,创建相应的类实例,当工厂类的创建实例方法被调用时,给调用者返回一个创建好的类实例。就可完成一个可通过修改配置,读取到不同的类,但实现相同规则的类实例。
首先因为是配置的,那么我们就先在app.config设置好配置的xml:
<appSettings>
<add key="DBSqlHelperConfig" value="Test.DB.MySqlHelper,Test.DB.MySqlHelper.MySqlHelper"/>
//这里的key值和value值可以自定义,格式可以根据自己喜好设置,我这里是value用逗号分隔,前面是dll名,后面是类名
</appSettings>
建factory类:
public static class Factory
{
private static string IDBSqlHelperConfig = ConfigurationManager.AppSettings["DBSqlHelperConfig"];
private static string DllName = IDBSqlHelperConfig.Split(',')[0];
private static string TypeName = IDBSqlHelperConfig.Split(',')[1];
public static ISqlHelper CreateSqlHelper()
{
Assembly assemblySqlHelper = Assembly.Load(DllName);
Type typeSqlHelper = assemblySqlHelper.GetType(TypeName);
ISqlHelper sqlHelper = Activator.CreateInstance(typeSqlHelper) as ISqlHelper;
return sqlHelper;
}
}
正式代码可直接使用工厂类,获取相应类的实例:
ISqlHelper sqlHelper = Factory.CreateSqlHelper();
到此处,就完成了一个反射的基本场景使用。好处就是如果在不同生产环境中使用,需要用不同的工具类时,同时这些类实现了相同的规则,通过修改配置,即可完成不同环境的部署和使用,不用修改代码。
前面说通过dll名和类名,可以实例化相应的类和使用类方法,那么.Net有泛型的说法。泛型类本身的实现即是通过类名占位符,在生成中间的编译文件时,先使用对应的占位符替代类名,当每次新构造一个泛型类时,就会将传进来的具体类名替换掉占位符,并在内存会初始化相应的类,并保留一份副本,如果下次使用相同类型的泛型类,类中的静态方法不会再次实例化,只会调用相应的实例方法,包括对应的private初始化器,并保存一份相应实例化的副本(非泛型类也会在实例化时调用相应的私有实例化器,所以在这点上,是不安全的)。
相同的,使用反射创建实例化泛型类,可以先通过获取具有占位符`Num(比如三个类名占位符就是 `3)的泛型类的类型,然后通过给相应占位符传实名类,获得具有实名类的类型,从而创建实例化泛型类。
代码如下:
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericClass`3");
Type newType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
object oGeneric = Activator.CreateInstance(newType);
实例化泛型方法
Type typeGenericDouble = assembly.GetType("Ruanmou.DB.SqlServer.GenericDouble`1");
Type newType = typeGenericDouble.MakeGenericType(new Type[] { typeof(int) });
object oGeneric = Activator.CreateInstance(newType);
MethodInfo method = newType.GetMethod("Show");
MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
methodNew.Invoke(oGeneric, new object[] { 123, "流浪诗人", DateTime.Now });
People people = new People();
people.Id = 123;
people.Name = "Lutte";
people.Description = "高级班的新学员";
Type typePeople = typeof(People);
Type typePeopleDTO = typeof(PeopleDTO);
object peopleDTO = Activator.CreateInstance(typePeopleDTO);
foreach (var filed in typePeopleDTO.GetFields())
{
object value = typePeople.GetField(filed.Name).GetValue(people);
filed.SetValue(peopleDTO, value);
}
上面对反射的使用进行简单的演示,实际的使用还要多加练习!