C# 反射 Reflection Assembly
本章节带来的是反射,反射反射程序员的快乐。
一、什么叫反射
反射:是.net Framework提供给的一个方面metadata的帮助类,可以获取信息并且使用
反射的有点:动态
反射的缺点:1:稍微麻烦 2:能避开编译器的检查 3:性能损耗
二、反射如何使用:
具体和私用如下:
#region 反射的加载方式
////获取当前路径下面的dl或者exe,不带后缀(MyReflection.exe 是编译后生成的exe执行文件),从Exe所在的路径进行查找
Assembly assembly = Assembly.Load(@"MyReflection");
//获取当前路径下面的dl或者exe
Assembly assemblyFrom = Assembly.LoadFrom(@"D:\MyReflection\bin\Debug\MyReflection.exe");
//获取当前路径下面的dl或者exe
Assembly assemblyFile = Assembly.LoadFile(@"D:\MyReflection\bin\Debug\MyReflection.exe");
foreach (var item in assembly.GetModules())
{
//Modules当前的exe或者dll的名字(MyReflection.exe)
Console.WriteLine(item.Name);
}
//当前所包含的实体类(IDBHelper,SqlServerHelper,Program)
foreach (var item in assembly.GetTypes())
{
foreach(var method in item.GetMethods()){
Console.WriteLine(method.Name);
}
Console.WriteLine(item.Name);
} foreach (var item in assembly.GetCustomAttributes())
{
Console.WriteLine(item.ToString());
}
//获取到有多个构造函数
foreach (var ctor in type.GetConstructors())
{
Console.WriteLine(ctor.GetParameters());
//获取构造函数里面的参数
foreach (var item in ctor.GetParameters())
{
Console.WriteLine(item.ParameterType);
}
}
#endregion
通过反射创建一个方法:
/// <summary>
/// 反射得到一个对象
/// </summary>
public class SimpleFactory
{
//读取配置文件AppSetting里面的key
// <appSettings>
// <add key = "DbConfig" value="MyReflection,MyReflection.MySqlServerHelper"/>
//</appSettings>
private static string ConfigStr = ConfigurationManager.AppSettings["DbConfig"];
private static string DllName = ConfigStr.Split(',')[]; //命名空间
private static string TypeName = ConfigStr.Split(',')[]; //类型要完整命名空间+类名
public static T CreateInstance<T>()
{
Assembly assembly = Assembly.Load(DllName);//加载dll
Type type = assembly.GetType(TypeName);//获取类型
var objectInstance = Activator.CreateInstance(type);
return (T)objectInstance; //要强制转换一下,因为牵涉到编译性语言和运行时语言
}
}
调用的时候如下:
var mysqlServerHelper = SimpleFactory.CreateInstance<MySqlServerHelper>();
mysqlServerHelper.Query();
三、反射调用多构造函数,调用私有构造函数(破坏单例),调用泛型类
首先创建一个实体类,包含有参无参构造函数,然后有参无参的方法,如下:
/// <summary>
/// sqlServer
/// </summary>
public class SqlServerHelper : IDBHelper
{
//private SqlServerHelper()
//{
// Console.WriteLine("私有构造函数");
//}
public SqlServerHelper()
{
Console.WriteLine("公有无参构造函数");
}
public SqlServerHelper(int iParam)
{
Console.WriteLine($"int的构造函数--{iParam}");
}
public SqlServerHelper(string sParam)
{
Console.WriteLine($"string的构造函数--{sParam}");
}
public SqlServerHelper(int iParam, string sParam)
{
Console.WriteLine($"int和string的构造函数--int={iParam} ;string={sParam}");
} public void Show()
{
Console.WriteLine("Show");
}
public void Show1()
{
Console.WriteLine("Show1的无参构造函数");
}
public void Show1(int iParam)
{
Console.WriteLine($"Show1的int重载--{iParam}");
}
public void Show1(int iParam, string sParam)
{
Console.WriteLine($"Show1两参数 iparam={iParam};sParam={sParam}");
}
public static void Show5(string name)
{
Console.WriteLine($"静态方法---{name}");
}
}
1:调用有参无参的public构造函数:
Assembly assembly = Assembly.Load("MyReflection"); //获取当前路径下面的dl或者exe,不带后缀
Type dbHelperType = assembly.GetType("MyReflection.SqlServerHelper"); //传完整名称获类型(命名空间+类名)
//调用多个构造函数(有参,无参)
var obSqlServerHelper = Activator.CreateInstance(dbHelperType); //无参的构造函数
Activator.CreateInstance(dbHelperType, new object[] { }); //int的构造函数
Activator.CreateInstance(dbHelperType, new object[] { "testbywss" }); //调用string的构造函数
Activator.CreateInstance(dbHelperType, new object[] { , "testbywss" }); //调用string的构造函数
2:调用private构造函数:
//私有构造函数
Type singletonType = assembly.GetType("MyReflection.Singleton"); //传入完整名称获取类型(命名空间+类名)
var object1 = Activator.CreateInstance(singletonType, true); //设置成true能调用私有/公布的构造函数,如果不设置则只能调用公有构造函数
3:普通方法,静态方法,重载方法的调用:
//普通方法
MethodInfo methodInfo = dbHelperType.GetMethod("Show"); //调用单个普通的实例方法
methodInfo.Invoke(obSqlServerHelper, null); //第一个参数:是应用对象,第二个参数:是方法需要的参数,如果没有则设置为null //静态方法调用
MethodInfo staticMethodInfo = dbHelperType.GetMethod("Show5"); //调用单个普通的实例方法
staticMethodInfo.Invoke(null, new object[] { "静态方法第一种调用方式" }); //第一个参数:是应用对象,如果是静态可以不用写;第二个参数:是方法需要的参数,如果没有则设置为null
staticMethodInfo.Invoke(obSqlServerHelper, new object[] { "静态方法第二种调用方式" }); //重载方法调用
MethodInfo method2 = dbHelperType.GetMethod("Show1", new Type[] { }); //调用无参的方法
method2.Invoke(obSqlServerHelper, null); MethodInfo method3 = dbHelperType.GetMethod("Show1", new Type[] { typeof(int) }); //int参数的方法
method3.Invoke(obSqlServerHelper, new object[] { }); MethodInfo method4 = dbHelperType.GetMethod("Show1", new Type[] { typeof(int), typeof(string) }); //调用2个参数的方法,new Type[] { typeof(int), typeof(string) } 顺序一定要跟调用的方法的参数顺序保持一致
method4.Invoke(obSqlServerHelper, new object[] { , "ddd" });
4:调用泛型,首先要创建一个实体类如下:
#region 泛型类
public class GenericClass<T, W, F>
{
public void Show(T t, W w, F f)
{
Console.WriteLine($"t.type={t.GetType().Name};}");
}
} public class GenericMethod
{
public void Show<T, W, X>(T t, W w, X x)
{
Console.WriteLine($"t.type={t.GetType().Name};");
}
} public class GenericDouble<T>
{
public void Show<W, X>(T t, W w, X x)
{
Console.WriteLine($"t.type={t.GetType().Name};");
}
}
#endregion
然后调用泛型方法如下:
//创建泛型
Assembly assembly = Assembly.Load("MyReflection"); //获取当前路径下面的dl或者exe,不带后缀
Type genericType = assembly.GetType("MyReflection.GenericClass`3"); //`3是泛型类需要的参数(占位符代表有三个类型参数)
Type typeGenericNew = genericType.MakeGenericType(typeof(int), typeof(int), typeof(int)); //需要指定泛型类的类型
GenericClass<int, int, int> oGeneric = (GenericClass<int, int, int>)Activator.CreateInstance(typeGenericNew);
oGeneric.Show(, , ); Type genericType1 = assembly.GetType("MyReflection.GenericMethod"); //普通的类
var genericMethod = Activator.CreateInstance(genericType1) as GenericMethod;
genericMethod.Show<int, string, double>(, "", );
5:调用私有方法(破坏单例)
//私有方法
//调用私有方法,有参数
MethodInfo method5 = dbHelperType.GetMethod("Show5", BindingFlags.NonPublic | BindingFlags.Instance);
method5.Invoke(obSqlServerHelper, new object[] { 5.0 }); //私有方法,无参数
MethodInfo method6 = dbHelperType.GetMethod("Show6", BindingFlags.NonPublic | BindingFlags.Instance);
method6.Invoke(obSqlServerHelper, null);
6:调用普通方法的泛型方法
//类的泛型方法调用
Type genericMethodType = assembly.GetType("MyReflection.GenericMethod");
var objectGeneric = Activator.CreateInstance(genericMethodType);
MethodInfo genericMethod = genericMethodType.GetMethod("Show");
//同样需要指定泛型方法的类型
MethodInfo genericMethodNew = genericMethod.MakeGenericMethod(typeof(int), typeof(int));
//一定要用genericMethodNew进行调用
genericMethodNew.Invoke(objectGeneric, new object[] { , });
四:反射的用途:
1:使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及此程序集中查找类型并且创建该类型的实力。
2:使用Module了解包含模块的程序集模块中的类等,还可以获取在模块上定义IDE所有全局方法或其他定义的非全局方法。
3:使用ConstructorInfo 了解构造函数的名字、参数、访问修饰符(如public 或private)和实现详细信息(如abstract或virtual)等。
4:使用MethodInfo 了解方法的名字、返回的类型、参数、参数类型、访问修饰符(如public 或private)和实现详情信息(如abstract或virtual)等。
5:使用FiedInfo了解字段名称、访问修饰符(如public 或private)和实现详细信息(如static)等,并获取或设置字段值。
6:使用PropertyInfo了解属性的名字、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
7:使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
8:使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中位置等。
9:使用Attribute了解特性的名字、使用特性的方法属性等。(点击跳转 C# 自定义特性Attribute的使用)
Console.WriteLine("*********************字段和属性***********************");
People people = new People()
{
ID = ,
Name = "名字",
Description = "描述"
};
Type typePeople = typeof(People);
object oPeople = Activator.CreateInstance(typePeople); //new 一个新的对象
//得到所有的字段public声明,但是么有set和get方法
foreach (var item in typePeople.GetFields())
{
Console.WriteLine($"Name1={item.Name};value1={item.GetValue(people)}");
} //得到所有的属性(有set和get的属性)
foreach (var item in typePeople.GetProperties())
{
if (item.Name.Equals("Id"))
{
item.SetValue(oPeople, );
}
else if (item.Name.Equals("Name"))
{
item.SetValue(oPeople, "人民");
}
Console.WriteLine($"Name={item.Name};value={item.GetValue(oPeople)}");
}
3:Type类的方法
GetConstructor(),GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息
GetEvent(),GetEvents():返回EventInfo类型,用于取得该类的事件的信息
GetField(),GetFields():返回FielInfo类型,用于取得该类的字段(成员变量)的信息
GetInterface(),GetInterfaces();返回InterfaceInfo类型,用于获得该类实现的接口信息
GetMember(),GetMembers();返回MemberInfo类型,用于取得该类的所有成员信息
GetMethod(),GetMethods();返回MethodInfo类型,用于取得该类的方法信息
GetProperty(),GetProperties();返回PropertyInfo类型,用于取得该类的属性的信息
六:普通方法和Reflection性能的比较
public class MySqlServerHelper
{
public MySqlServerHelper()
{
}
public void Query()
{ }
}
public class Monitor
{
public static void Show()
{
Console.WriteLine("*******************Monitor*********");
long commonTime = ;
long reflectionTime = ;
{
//时间测量工具
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = ; i < ; i++)
{
MySqlServerHelper dbHelper = new MySqlServerHelper();
dbHelper.Query();
}
watch.Stop();
commonTime = watch.ElapsedMilliseconds; //毫秒
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
//1:动态加载
Assembly assembly = Assembly.Load("MyReflection");
//2:获取类型
Type type = assembly.GetType("MyReflection.MySqlServerHelper");
for (int i = ; i < ; i++)
{
MySqlServerHelper oDbHelper =(MySqlServerHelper)Activator.CreateInstance(type);
oDbHelper.Query();
}
watch.Stop();
reflectionTime = watch.ElapsedMilliseconds;
}
Console.WriteLine($"reflectionTime={reflectionTime};commonTime={commonTime}");
}
}
然后调用后发现: 100万次相差30倍左右,所以反射的是很耗性能,但是如果分布到每次则相差几毫秒,所以这个性能影响可以忽略掉!
七:继承后的子类,只需要获取子类的属性:
t.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); //不要父类的属性,只要子类的属性
C# 反射 Reflection Assembly的更多相关文章
- C# 反射Reflection Assembly
反射反射程序员的快乐 一:什么叫反射 反射:是.net framework提供的一个访问metadata的帮助类,可以获取信息并且使用 反射的优点:动态 反射的缺点:1:稍微麻烦 2:能避开编译器的 ...
- [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- 反射(Reflection)
反射主要用于在程序运行期间动态解析相关类的类名,命名空间,属性,方法并进行相应操作,以下通过两个简单的例子进行了说明: 示例1:调用程序集内部方法,运行时动态获取相关类的信息,包括类名,命名空间等信息 ...
- [整理]C#反射(Reflection)详解
本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...
- C#-反射reflection
目录 简介 引入 1.新建类库 2. 类库的使用 3.反射 反射实例1 反射实例2 反射实例3 C# shanzm 简介 反射(reflection)是什么? 在<精通C#>中是这么说的& ...
- C# 反射(Reflection)技术
本文参考自C#反射(Reflection)详解,纯属学习笔记,加深记忆 在介绍反射前,先介绍一个重要的知识点 .Net应用程序是由程序集(Assembly).模块(Module).类型 ...
- C# 反射(Reflection)
反射主要用于在程序运行期间动态解析相关类的类名,命名空间,属性,方法并进行相应操作,以下通过两个简单的例子进行了说明: 示例1:调用程序集内部方法,运行时动态获取相关类的信息,包括类名,命名空间等信息 ...
- C#反射(Reflection)详解
1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什么是反 ...
随机推荐
- spring 与mybatis 整合总结
刚看完同学给我的代码,我忍不住爆粗.去TMD,写得像坨屎,恶心,乱七八糟,这让我怎么交差??一行代码注释都没有,还很自以为是的傲慢.“这都不懂?这就是Mybatis啊,有很多种方法实现.....” 操 ...
- 【转】fatal error C1189: #error : missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS
转自:http://blog.csdn.net/friendan/article/details/46576699 fatal error C1189: #error : missing -D__S ...
- 一、C#简单读写
using System.IO; static string configFileName = "config.json"; //不存在就直接新建文件夹 public static ...
- Current_Path 获取脚本所在路径(当前路径),取当前时间做文件名(uformat)
获取脚本当前所在路径: $CurrentPath = $MyInvocation.MyCommand.Path.substring(0,$MyInvocation.MyCommand.Path.Las ...
- Sybase常用时间日期函数
Sybase日期函数日期函数getdate()得到当前时间,可以设置得到各种时间格式.datepart(日期部分,日期)取指定时间的某一个部分,年月天时分秒.datediff(日期部分,日期1,日期2 ...
- Web前端——jQuery----细节
jQuery终极思想:创建jQuery对象(当发现相同的选择器在你的代码里出现多次时,请用变量把它储存起来.一切面向对象) 认识jQuery 1.jQuery库可以做什么? HTML元素选取 HTML ...
- 沉淀再出发:ElasticSearch的中文分词器ik
沉淀再出发:ElasticSearch的中文分词器ik 一.前言 为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了 ...
- December 30th 2016 Week 53rd Friday
Life without love is like a tree without blossoms or fruit. 缺少爱的生活就像从未开花结果的枯树. Love is not only the ...
- markdown编辑器安装
打算使用MarkDown了,打算整理自己的知识了. 多年以前,喜欢将自己看到好东西,转载在博客.或者将遇到过的问题以及解决方案,记录在博客.06毕业后为了生活折腾,Tom网上的博客无暇东顾,等稳定闲下 ...
- python选课系统
程序名称: 选课系统 角色:学校.学员.课程.讲师 要求: 1. 创建北京.上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海 ...