反射反射程序员的快乐
一:什么叫反射
反射:是.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);
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了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 
3:使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。 
4:使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
5:使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
6:使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。 
7:使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。 
8:使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。

五:反射类以及属性的介绍:
 
1:反射用到的主要类:
    System.Type 类--通过这个类可以访问任何给定数据类型的信息。
    System.Reflection.Assembly类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。
 
2: Type类的属性:
        Name 数据类型名
        FullName 数据类型的完全限定名(包括命名空间名)
        Namespace 定义数据类型的命名空间名
        IsAbstract 指示该类型是否是抽象类型
        IsArray   指示该类型是否是数组
        IsClass   指示该类型是否是类
        IsEnum   指示该类型是否是枚举
        IsInterface    指示该类型是否是接口
        IsPublic 指示该类型是否是公有的
        IsSealed 指示该类型是否是密封类
        IsValueType 指示该类型是否是值类型
        IsGenericType 判断是否是泛型类
  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():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
        GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息
        GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
        GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息
        GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息
    可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法。 
 
六:普通方法和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的更多相关文章

  1. C# 反射 Reflection Assembly

    本章节带来的是反射,反射反射程序员的快乐. 一.什么叫反射 反射:是.net Framework提供给的一个方面metadata的帮助类,可以获取信息并且使用 反射的有点:动态 反射的缺点:1:稍微麻 ...

  2. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  3. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  4. 反射(Reflection)

    反射主要用于在程序运行期间动态解析相关类的类名,命名空间,属性,方法并进行相应操作,以下通过两个简单的例子进行了说明: 示例1:调用程序集内部方法,运行时动态获取相关类的信息,包括类名,命名空间等信息 ...

  5. [整理]C#反射(Reflection)详解

    本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...

  6. C#-反射reflection

    目录 简介 引入 1.新建类库 2. 类库的使用 3.反射 反射实例1 反射实例2 反射实例3 C# shanzm 简介 反射(reflection)是什么? 在<精通C#>中是这么说的& ...

  7. C# 反射(Reflection)技术

    本文参考自C#反射(Reflection)详解,纯属学习笔记,加深记忆 在介绍反射前,先介绍一个重要的知识点         .Net应用程序是由程序集(Assembly).模块(Module).类型 ...

  8. C# 反射(Reflection)

    反射主要用于在程序运行期间动态解析相关类的类名,命名空间,属性,方法并进行相应操作,以下通过两个简单的例子进行了说明: 示例1:调用程序集内部方法,运行时动态获取相关类的信息,包括类名,命名空间等信息 ...

  9. C#反射(Reflection)详解

    1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什么是反 ...

随机推荐

  1. spring BeanPostProcessor

    BeanPostProcessor spring使用BeanPostProcessor接口来处理生命周期的回调 BeanPostProcessor接口定义的两个方法,分别在bean的(实例化配置和初始 ...

  2. Apache Tomcat Eclipse Integration

    An Illustrated Quick Start Guide Apache Tomcat makes hosting your applications easy. The Eclipse IDE ...

  3. python 变量,if,while,运算符

    变量由变量名 赋值 值 a = 1 ###### 必须是一个等于号 一个等于号是赋值 变量的命名规则: 1.数字,字母,下划线组成 2.数字不能在前面 3.区分大小写 4.禁止使用python关键字 ...

  4. 执行一个内容为SQL语句的字符串

    两种方式:exec (sqlStr);或exec sp_executesql @sqlStr;绝大多数情况下,应使用第二种方式来执行动态sql.因为这种方式能重用执行计划,并且更安全. 参考例子:ht ...

  5. Metasploit Framework(5)弱点扫描

    文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 当我们发现了目标机器开放的端口,开启的服务等等之后 就 ...

  6. [Swift]Alamofire:设置网络请求超时时间【timeout】的两种方式

    两种方式作用相同,是同一套代码的两种表述. 第一种方式:集聚. 直接设置成员属性(全局属性),这种方法不能灵活修改网络请求超时时间timeout. 声明为成员属性: // MARK: - 设置为全局变 ...

  7. Python制作二维码和条形码扫描器 (pyzbar)

    条码在生活中随处可见,其可分为三类:一维条码.二维条码.三维条码 一维条码: 我们平时习惯称为条形码.条形码是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常见的条 ...

  8. dedecms中arclist标签做分页以及分页点击模块样式错乱问题

    in 使用织梦建站,通常会调用到一个文章列表,dedecms官网list标签没有提供typeid的属性,首页或多列表部分情况下使用分页并不方便,这就需要用arclist标签实现一个分页功能:以下还是展 ...

  9. Jade —— 源于 Node.js 的 HTML 模板引擎

    2013-12-11 发布 Jade —— 源于 Node.js 的 HTML 模板引擎 开源项目介绍 web 模板引擎 node.js jade 207.8k 次阅读  ·  读完需要 69 分钟 ...

  10. Tomcat添加HTTPS单向认证和双向认证

    前言 前一段时间有了解如何配置Tomcat服务为Https单向认证和双向认证,当时也做了一些记录,今天开始写博客,就把以前的记录拿出来整理下,分享给大家.本文没有介绍证书如何生成,会在下一篇博文里介绍 ...