# C# 反射 (Reflect)

1.基本内容

我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

最基本的调用:

Assembly assembly = Assembly.Load("DB.SqlServer");//将加载dll
Type type = assembly.GetType("DB.SqlServer.SqlServerHelper");//得到DLL 中的SqlServerHelper 类
object obj = Activator.CreateInstance(type);//创建类的实例
SqlServerHelper helper = (SqlServerHelper)obj;//将创建的Object 对象转换为SqlServerHelper对象
helper.Query();//调用对象的方法

2.创建对象

工厂方法

反射的一个应用场景是,当我们开发的程序的数据库是可能变化时,就会用到反射,入下述代码:

//这是一个DB接口层
namespace DB.Interface
{public interface IDBHelper{void Query();}
}
//这是SqlServer数据库的操作层
namespace DB.SqlServer
{public class SqlServerHelper : IDBHelper//继承自DB接口层{public void Query(){Console.WriteLine("我是{0}", typeof(SqlServerHelper));}}
}
//这是MySql数据库的操作层
namespace DB.MySql
{public class MySqlHelper : IDBHelper//继承自DB接口层{public void Query(){Console.WriteLine("我是{0}", typeof(MySqlHelper));}}
}

然后我们会建造一个工厂类,专门用于生产对象:

//这是工厂层
public class Factory
{static string IDBHelperConfig = System.Configuration.ConfigurationManager.AppSettings["IDBHelperConfig"];static string DllName = IDBHelperConfig.Split(',')[0];static string TypeName = IDBHelperConfig.Split(',')[1];public static IDBHelper CreateDBHelper(){Assembly assembly = Assembly.Load(DllName);//将加载dll Type type = assembly.GetType(TypeName);//得到DLL 中的SqlServerHelper 类object obj = Activator.CreateInstance(type);//创建类的实例return (IDBHelper)obj;//将创建的Object 对象转换为IDBHelper对象 并返回}
}

然后在app.config 文件中添加配置:

<appSettings><!--这是配置字符串--><add key="IDBHelperConfig" value="DB.SqlServer,DB.SqlServer.SqlServerHelper"/>
</appSettings>

最后在调用层面调用:

//这是调用
IDBHelper dbHelper = Factory.CreateDBHelper();
dbHelper.Query();

这样当数据库从SqlServer 修改为 MySql 时,我们只需要修改app.config中的配置字符串即可,而不需要修改源代码,这样有利于我们程序的维护,与稳定。

带参数对象创建

基础类

namespace Model
{public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public Person(int id){Console.WriteLine("我是有1个参数的构造函数!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2个参数的构造函数!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3个参数的构造函数!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,无参数构造函数");}}
}

有参数的构造函数调用方式:

Assembly assembly = Assembly.Load("Model");
Type personType = assembly.GetType("Model.Person");
//调用带1个参数的构造函数
object obj = Activator.CreateInstance(personType, new object[] { 123 });
//调用带2个参数的构造函数
object obj2 = Activator.CreateInstance(personType, new object[] { 123, "Oliver" });
//调用带3个参数的构造函数
object obj3 = Activator.CreateInstance(personType, new object[] { 123, "Oliver", DateTime.Now });

调用私有构造函数

Assembly assembly = Assembly.Load("Model");
Type personType = assembly.GetType("Model.Person");
//调用私有函数
object obj4 = Activator.CreateInstance(personType,true);

泛型类创建

基础类

namespace Model
{//添加泛型类public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型类的构造函数!");}public T GetT(){return default(T);}}
}

通过反射的方法创建泛型对象

Assembly assembly = Assembly.Load("Model");
Type gennericClassType = assembly.GetType("Model.GenericClass`1");//如果是一个泛型需要在后面添加`1,否则取出来的时NULL
Type newGennericClassType = gennericClassType.MakeGenericType(new Type[] { typeof(int) });
var obj = Activator.CreateInstance(newGennericClassType);

注意反射泛型类的时候GetType方法传入的类名称,需要在后面添加相应的泛型个数。下面这句代码也相应的说明这个情况。

//输出的值也会有一个`1
Console.WriteLine(typeof(GenericClass<int>));//输出:Model.GenericClass`1[System.Int32]

3.调用方法

基础类

namespace Model
{public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public string Memo;//字段public Person(int id){Console.WriteLine("我是有1个参数的构造函数!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2个参数的构造函数!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3个参数的构造函数!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,无参数构造函数");}//带有返回值的无参方法public DateTime Show(){Console.WriteLine("我是带有返回值的无参方法。");return DateTime.Now;}//带有参数的方法public void Show2(int i){Console.WriteLine("我是Show2(int i).i=" + i);}//重载方法public void Show3(int i){Console.WriteLine("我是Show3(int i).i=" + i);}//重载方法public void Show3(string s){Console.WriteLine("我是Show3(string s).s=" + s);}//私有方法private void Show4(){Console.WriteLine("我是私有方法");}//静态方法public static void Show5(){Console.WriteLine("我是静态方法");}}
}

无参方法

Assembly assembly = Assembly.Load("Model");//加载dll
Type personType = assembly.GetType("Model.Person");//得到类
object objPerson = Activator.CreateInstance(personType, true);//创建对象
//调用 有返回值 无参数的方法
MethodInfo show = personType.GetMethod("Show");//找到方法
DateTime dt = (DateTime)(show.Invoke(objPerson, new object[] { }));//调用,并接收返回值

带参数方法

//调用 带有参数的方法
MethodInfo show2 = personType.GetMethod("Show2");
show2.Invoke(objPerson, new object[] { 123 });

重载方法

//调用 重载方法1
MethodInfo show3 = personType.GetMethod("Show3", new Type[] { typeof(int) });
show3.Invoke(objPerson, new object[] { 234 });//调用 重载方法2
MethodInfo show3_1 = personType.GetMethod("Show3", new Type[] { typeof(string) });
show3_1.Invoke(objPerson, new object[] { "ABC" });

私有方法

//调用私有方法
MethodInfo show4 = personType.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
show4.Invoke(objPerson, new object[] { });

静态方法(两种形式)

//调用静态方法
MethodInfo show5 = personType.GetMethod("Show5");
show5.Invoke(objPerson, new object[] { });//类似于 实例调用
show5.Invoke(null, new object[] { });//类似于直接通过类名称调用

调用泛型类的泛型方法

基础类

namespace Model
{//添加泛型类public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型类的构造函数!");}public T GetT<S>(T t, S s){Console.WriteLine("我是泛型类中的泛型方法!t_type:{0}, t_value:{1}\ts_type:{2}, s_value:{3}", typeof(T), t, typeof(S), s);return t;}}
}

调用GenericClass类的GetT方法

Assembly assembly = Assembly.Load("Model");
Type genericClassType = assembly.GetType("Model.GenericClass`1");//`1 千万别忘记
Type newGenericClassType = genericClassType.MakeGenericType(new Type[] { typeof(int) });
object obj= Activator.CreateInstance(newGenericClassType);//创建对象
MethodInfo methodInfo = newGenericClassType.GetMethod("GetT");
MethodInfo newMethodInfo = methodInfo.MakeGenericMethod(new Type[] {  typeof(string) });
newMethodInfo.Invoke(obj, new object[] { 123, "Oliver" });//输出:我是泛型类中的泛型方法!t_type:System.Int32, t_value:123       s_type:System.String, s_value:Oliver

4.get set 属性、字段

属性操作

Person p = new Person(1, "Oliver", DateTime.Now);
Type t = p.GetType();
PropertyInfo propertyInfo = t.GetProperty("Id");
Console.WriteLine(propertyInfo.GetValue(p));//获取 属性的值。输出 1
propertyInfo.SetValue(p,123);//获取 属性的值
Console.WriteLine(propertyInfo.GetValue(p));//设置 属性的值。输出 123//遍历属性
foreach (var prop in t.GetProperties())
{Console.WriteLine("{0}.{1}={2}", typeof(Person), propertyInfo.Name, prop.GetValue(p));/*输出:Model.Person.Id=123Model.Person.Id=OliverModel.Person.Id=2018/8/8 22:15:09*/
}

字段操作

Person p = new Person(1, "Oliver", DateTime.Now);
Type t = p.GetType();
FieldInfo fieldInfo = t.GetField("Memo");
Console.WriteLine(fieldInfo.GetValue(p));//获取 属性的值。输出 空字符串
fieldInfo.SetValue(p, "自律给我自由");//获取 属性的值
Console.WriteLine(fieldInfo.GetValue(p));//设置 属性的值。输出 自律给我自由

转载于:https://www.cnblogs.com/haowuji/p/9446118.html

C# 反射 (Reflect)相关推荐

  1. Golang的反射reflect深入理解和示例

    [TOC] Golang的反射reflect深入理解和示例 [记录于2018年2月] 编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机 ...

  2. 反射 reflect

    反射 reflect 什么是反射,其实就是反省,自省的意思 反射指的是以一个对象应该具备,可以检测,修改,增加自身属性的能力 反射就是通过字符串操作属性 涉及到的四个函数,这四个函数就是普通的内置函数 ...

  3. 浅谈Java反射(Reflect)技术--常用方法

    Java反射(Reflect)技术 概念:动态获取在当前Java虚拟机中的类.接口或者对象等等信息(运行过程中读取内容) 1.作用(面试问题): 1.1 解除两个类之间的耦合性,即在未得到依赖类的情况 ...

  4. go struct 静态函数_Go语言学习笔记(四)结构体struct 接口Interface 反射reflect...

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  5. 反射(reflect)机制

    什么是反射 官方对此有个非常简明的介绍,两句话耐人寻味: 反射提供一种让程序检查自身结构的能力 反射是困惑的源泉 要深刻理解反射,个人感觉需要花时间在官方博客上再加以练习,循序渐进,慢慢体会. 反射的 ...

  6. go使用反射reflect获取变量类型

    可以用反射: package mainimport ("fmt""reflect" )func main() {var x float64 = 3.4fmt.P ...

  7. Golang实践录:利用反射reflect构建通用打印结构体接口

    本文针对 Golang 的结构体字段的打印进行一些研究.其中涉及到一些反射的知识. 问题提出 总结一些实践情况,结构体字段值的输出还是比较常见的,至少笔者目前常用.比如输出某些数据表的数据(代码中会转 ...

  8. Go语言--反射(reflect)

    0 反射的概念 反射是指计算机程序在运行时(runtime)可以访问.检测和修改本身状态或行为的一种能力.通俗地将,反射就是程序能够在运行时动态地查看自己的状态,并且允许修改自身的行为. 程序在编译时 ...

  9. 反射 Reflect Class 基础 API MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  10. golang 反射 reflect 设置 struct 字段

    目录 说明1 reflect.Value区分CanSet和Can not Set 说明2 将值转成reflect.Value类型 说明3  reflect.ValueOf 参数必须是一个 指针 或   ...

最新文章

  1. python+selenium百度贴吧自动签到
  2. git使用的详细过程
  3. b区计算机考研招不满的大学,b区考研招不满的大学,适合调剂的学校有哪些
  4. x位全排列(next_permutation)
  5. AO安装需要Microsoft Visual Studio 2013?
  6. 解析 http 请求 header 错误_详解http报文(2)-web容器是如何解析http报文的
  7. 【Linux】7_存储管理基本分区
  8. Object类和常用API
  9. hibernate.hbm2ddl.auto配置详解
  10. 2017.10.12 礼物(zjoi2011) 失败总结
  11. mbed OS - ARM关于物联网(IoT)的战略布局
  12. PyCharm----中文显示乱码的解决方法总结
  13. Python操作Redis例子
  14. Backtrack 4 – Bootable USB Thumb Drive with “Full” Disk Encryption
  15. 如何快速的切换EXCEL
  16. BIGEMAP离线数据包网盘下载密码:1111
  17. 用vue2写一个新闻列表页,和新闻详情页,该怎么做?
  18. uni-app获取当前时间日期及之后7天和星期几
  19. Node rar压缩/解压文件
  20. Spark面试精选题(05)

热门文章

  1. *【HDU - 5707】Combine String(dp)
  2. 【HDU - 2255】奔小康赚大钱(KM算法模板,二分图最优匹配)
  3. php 取oracle图片,在PHP中将图片存放ORACLE中_php
  4. 云服务器怎么装mysql_云服务器(windows环境)安装mysql图文教程
  5. 40029错误{“errcode“:40029,“errmsg“:“invalid code, rid: 623bbdcd-3c97f4af-5a2c06d6“}
  6. mysql将时间轴转化为时间_MySQL日期计算及格式转换有关问题
  7. dataset的去重计数 g2_向工程渣土运输车辆计数 漏洞损失说“不”
  8. 充分条件反过来是必要条件吗_“充分必要条件”引发的现实思考
  9. oracle 12 ORA-01262,oracle物理dg安装:方法二
  10. oracle推送短信,ORACLE 10G如何实现发短信的服务?