zoukankan      html  css  js  c++  java
  • 反射(2)使用反射

      这一篇文章来总结下怎么使用反射的。

    加载程序集

    要加载程序集,可以调用 Assembly的LoadXXX系列方法。

    1,Assembly.Load方法

    1 //1,从GAC或应用程序基目录加载程序集
    2 var assembly = Assembly.Load("ReflectionDemo.A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");//或ReflectionDemo.A也可以

    需要注意的是:

    1)查找顺序,首先去GAC查找,如果没找到,则去应用程序的基目录查找,如果都没找到,则会抛出FileNotFoundException的异常。

    2)Load参数一般为应用程序集名称的长格式,如:ReflectionDemo.A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null,也可以直接ReflectionDemo.A。

    2,Assembly.LoadFrom方法

    1 //2,从一个url加载程序集
    2 var assembly = Assembly.LoadFrom(@"http://www.a.com/ReflectionDemo.A.dll"); 

    Assembly.LoadFrom的内部其实是调用Assembly.Load方法,唯一的不同在于,其可以从一个网络url中加载程序集。

    3,Assembly.LoadFile方法

    1 //3,从本地路径加载程序集
    2 var path = string.Format(@"{0}{1}", AppDomain.CurrentDomain.BaseDirectory, @"pluginsReflectionDemo.A.dll");
    3 var assembly = Assembly.LoadFile(path);

    Assembly.LoadFile允许从本地不同路径加载程序集。

    查找程序集内所有类型

    反射的入口Type类,Type对象提供的属性和方法可以获取对明的一切信息,包括:字段,属性,方法和事件等等。

    在已经加载了程序集的基础上,能过以下方式可以获取到Type对象。

     1 /// <summary>
     2 /// 获取程序集中所有的公共类型
     3 /// </summary>
     4 /// <param name="assembly"></param>
     5 static void GetExportedTypes(Assembly assembly)
     6 {
     7     var types = assembly.GetExportedTypes();
     8     foreach (var item in types)
     9     {
    10         Console.WriteLine(item.Name);
    11     }
    12 }
    1 /// <summary>
    2 /// 获取程序集中具名的类型
    3 /// </summary>
    4 /// <param name="assembly"></param>
    5 static void GetType(Assembly assembly)
    6 {
    7     var t = assembly.GetType("ReflectionDemo.A.Class1");
    8     Console.WriteLine(t.Name);
    9 }

    查找类型成员

    在命名空间System.Reflection下有一个抽象类MemberInfo,它封装了与类型成员相关的通用属性,每一个类型成员都有一个对应的从MemberInfo派生而来的类型,并且内置了一些特殊的属性特征,如FieldInfo、MethodBase(ContructorInfo、MethodInfo)、PropertyInfo和EventInfo。可以通过调用类型Type对象的GetMembers方法获取该类型的所有成员或相应成员,如下代码(对上面的GetTypes方法的修改)获取全部成员列表:

     1 /// <summary>
     2 /// 获取类型成员
     3 /// </summary>
     4 /// <param name="t"></param>
     5 static void GetMembers(Type t)
     6 {
     7     var members= t.GetMembers();
     8     foreach (var item in members)
     9     {
    10         Console.WriteLine(item.Name);
    11     }
    12 }

    Type对象有一组GetXXX方法是用来获取对象成员的,如下:

    GetConstructor/GetConstructors //获取构造函数
    GetField/GetFields //获取字段
    GetProperty/GetProperties //获取属性
    GetMethod/GetMethods //获取方法
    GetEvent/GetEvents //获取事件

    看下MemberInfo的结构:

    构造类型实例

    拿到类型和成员相关信息后,就可以创建类型的实例了,创建类型实例有以下几种方法:

    1 Activator.CreateInstance() //重载系列
    2 Activator.CreateInstanceFrom() //重载系列
    3 AppDomain.CurrentDomain.CreateInstance() //重载系列
    4 AppDomain.CurrentDomain.CreateInstanceFrom() //重载系列

    下面就来创建一个ReflectionDemo.A.Class1的实例(对象),如下代码:

    1 /// <summary>
    2 /// 创建类型实例
    3 /// </summary>
    4 static void CreateInstance(Assembly assembly)
    5 {
    6     var t = assembly.GetType("ReflectionDemo.A.Class1");
    7     var obj = Activator.CreateInstance(t);
    8 }

    访问实例成员

    创建了类型的实例后,就可以调用实例的成员方法了,如下代码:

     1 /// <summary>
     2 /// 动态调用方法
     3 /// </summary>
     4 /// <param name="assembly"></param>
     5 static void InvokeMethod(Assembly assembly)
     6 {
     7     var t = assembly.GetType("ReflectionDemo.A.Class1");
     8     var obj = Activator.CreateInstance(t);
     9 
    10     var name = t.InvokeMember("GetName", BindingFlags.InvokeMethod, null, obj, null);
    11 }

    上面演示了动态调用实例成员,访问实例其它成员可以通过BindingFlags来改变。

    反射对泛型的支持

    前面演示的都是普通类型,如果是泛型,该怎么处理呢?

    首先定义一个泛型类,如下:

     1 namespace ReflectionDemo.A
     2 {
     3     public class Class2<T> where T : class
     4     {
     5         public string GetName<T>(T name)
     6         {
     7             return string.Format("generic name,{0}", name.ToString());
     8         }
     9     }
    10 }

    演示一下如何调用泛型类的GetName方法,如下代码:

     1 /// <summary>
     2 /// 访问泛型类型成员
     3 /// </summary>
     4 /// <param name="assembly"></param>
     5 static void InvokeGenericMethod(Assembly assembly)
     6 {
     7     var types = assembly.GetExportedTypes();
     8     foreach (var item in types)
     9     {
    10         if (item.IsGenericType)//1,先判断是否为泛型
    11         {
    12             var obj = Activator.CreateInstance(item.MakeGenericType(new Type[] { typeof(string) }));//2,在创建泛型类实例前,必须调用MakeGenericType创建一个真正的泛型
    13             var methodInfo = obj.GetType().GetMethod("GetName").MakeGenericMethod(new Type[] { typeof(string) });//3,在调用泛型方法前,必须调用MakeGenericMethod创建一个真正的泛型方法
    14 
    15             var name = methodInfo.Invoke(obj, new object[] { "aaa" });
    16             Console.WriteLine(name);
    17         }
    18     }
    19 }
  • 相关阅读:
    超级有用的15个mysqlbinlog命令
    表迁移工具的选型-复制ibd的方法-传输表空间
    误删mysql表物理文件的解决方法(不涉及恢复数据)
    美团SQL优化工具SQLAdvisor
    Linux网络状态工具ss命令使用详解
    MySQL应用架构优化-实时数据处理
    运维利器万能的 strace
    ngrep命令用法
    [Linux|DBA]运维三十六计
    sysbench使用
  • 原文地址:https://www.cnblogs.com/mcgrady/p/6994206.html
Copyright © 2011-2022 走看看