.Net 反射用法

文章目录

  • 前言
  • 一、反射是什么?
  • 二、反射的使用
    • 1.反射加载实体类、实例方法
    • 2、反射实现工厂可配置类
    • 3、反射调用泛型类、泛型方法
    • 4、反射使用类字段和类属性
  • 总结


前言

1、反射加载实体类、实例方法
2、反射实现工厂可配置类
3、反射调用泛型类、泛型方法
4、反射使用类字段和类属性


提示:以下是本篇文章正文内容,下面案例可供参考

一、反射是什么?

     反射结合.Net编译器第一次编译生成的文件Metadata文件,加载其中的类、字段、方法信息,不直接使用类名而实例化类和使用类、类成员的一种手段。
    该手段提供一定的方便:动态
    也会有一定的缺点:1、写起来繁琐
                      2、避开编译器的检查,不会有语法错误提示,可以通过一定手段访问类的私有成员
                      3、 性能问题,这个影响其实网上说的特别多,但是实际的使用其实可以忽略,比如MVC使用的反射通过路由找到对应到控制器和调用的方法成员。EF也通过反射实现。通常第一次加载慢,后面会很快.

二、反射的使用

1.反射加载实体类、实例方法

代码如下(示例):

   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);//新实例

2、反射实现工厂可配置类

    反射实现工厂可配置的类,是通过在配置文件里面,写好要创建类实例的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();

到此处,就完成了一个反射的基本场景使用。好处就是如果在不同生产环境中使用,需要用不同的工具类时,同时这些类实现了相同的规则,通过修改配置,即可完成不同环境的部署和使用,不用修改代码。


3、反射调用泛型类、泛型方法

    前面说通过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 });

4、反射使用类字段和类属性

    

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);
}

总结

上面对反射的使用进行简单的演示,实际的使用还要多加练习!

你可能感兴趣的:(c#,c#)