C#反射(Reflection)详解

作者:Ruby_Lu 时间:2022-09-16 22:58:11 

C#反射技术主要基于System.Type类和System.Reflection.Assemble类,通过Type类可以访问关于任何数据类型的信息,Assemble类用于访问给定程序集的相关信息,或把这个程序集加载到程序中。

一.System.Type类

Type类是一个抽象类。只要实例化了一个Type对象,实际上就实例化了Type的一个派生类。尽管一般情况下派生类只提供各种Type方法和属性的不同重载,但是这些方法和属性返回对应数据类型的正确数据,Type有与每种数据类型对应的派生类。它们一般不添加新的方法或属性
通常,获取指向任何给定的Type引用有三种常用方式:

  • *使用typeof运算符,这个运算符的参数是类型的名称,但不放在引号中:

Type t =typeof(double);
  • *使用GetType()方法,所以类都会从System.Object继承这个方法:

double d =10;
Type t = d.GetType();

在一个变量上调用GetType()方法,返回的Type对象只与该数据类型相关,不包含该类型实例的任何信息。

  • *调用Type类的静态方法GetType():

Type t =Type.GetType("System.Double");

Type是很多反射功能的入口,它实现很多方法和属性,可用的属性都是只读的:可以使用Type确定数据的类型,但不能使用它修改该类型。

1.Type属性

由Type实现的属性分为3类。

  • *包含与类相关的各种名称的字符串:

    • Name:数据类型名

    • FullName:数据类型的完全限定名(包含名称空间)

    • Namespace:在其中定义数据类型的名称空间名

  • *获取Type对象的引用的属性:

    • BaseType:该对象的直接基本类型

    • UnderlyingSystemType:该Type在.NET运行库中映射到的类型

  • *布尔属性

    • IsAbstract,IsArray,IsClass,IsEnum等判断Type是什么类型的属性。

2.方法

System.Type的大多数方法都用于获取对应数据类型的成员信息:构造函数,属性,方法和事件等。它有许多方法,但它们都有相同的模式。例如,获取数据类型的方法的信息:GetMethod()和GetMethods()。GetMethod()方法返回MethodInfo对象的一个引用,其中包含一个指定方法的细节信息;而GetMethods()返回这种引用的一个数组。

C#反射(Reflection)详解

二.Assembly类

Assembly类允许访问给定程序集的元数据,它也包含可以加载和执行程序集(假定该程序集是可执行的)的方法。与Type类一样,Assembly类包含非常多的方法和属性,这里只介绍与特性(//www.jb51.net/article/244250.htm)有关的成员,其它成员可以去MSDN(https://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.100).aspx)查看。

C#反射(Reflection)详解

C#反射(Reflection)详解

C#反射(Reflection)详解

在使用Assembly实例做一些工作前,需要把相应的程序集加载到正在运行的进程中。可以使用静态方法Assembly.Load()或Assembly.LoadFrom()。Load()方法的参数程序集的名称,运行库会在各个位置上搜索该程序集,这些位置包括本地目录和全局程序集缓存。而LoadFrom()方法的参数是程序集的完整路径名,它不会在其它位置搜索该程序集:

Assembly assembly1 = Assembly.Load(“WhatsNewAttributes");
Assembly assembly2 = Assembly.LoadFrom(“E:\WhatsNewAttributes\bin\Debug\WhatsNewAttributes");

这两个方法都有许多其它重载版本。

1.获取在程序集中定义的类型的详细信息

Assembly类调用GetType()方法可以获得相应程序集中定义的所有类型的详细信息,它返回一个包含所有类型的详细信息的System.Type引用数组:

Type[] types = assembly1.GetType();

foreach(Type t in types)
{

}

2.获取自定义特性的详细信息

如果需要确定程序集关联了什么自定义特性,就需要调用Attribute类的一个静态方法GetCustomAttributes():

Assembly assembly1 = Assembly.Load(“WhatsNewAttributes");
Attribute[] attribs = Attribute.GetCustomAttributes(assembly1);

GetCustomAttributes方法用于获取程序集的特性,他有两个重载方法:如果在调用它时,除了程序集的引用外,没有其它参数,该方法就会返回这个程序集定义的所以自定义特性;如果指定第二个参数,第二个参数表示特性类的一个Type对象,GetCustomAttributes方法返回指定特性类型的特性数组。
所有的特性都作为一般的Attribute引用来获取。如果需要调用为自定义特性定义的任何方法或属性,就需要把这些引用显示转换为自定义特性类。
如果要获得与方法,构造函数和字段等的特性,就需要调用MethodInfo,ConstructorInfo,FieldInfo等类的GetCustomAttributes()方法。
下面通过一个例子演示,自定义特性和反射

1.编写自定义特性

namespace WhatsNewAttributes
   {
       [AttributeUsage(
           AttributeTargets.Class | AttributeTargets.Method,
           AllowMultiple = true, Inherited = false)]
       public class LastModifiedAttribute : Attribute
       {
           private readonly DateTime _dateModified;
           private readonly string _changes;

public LastModifiedAttribute(string dateModified, string changes)
           {
               _dateModified = DateTime.Parse(dateModified);
               _changes = changes;
           }

public DateTime DateModified
           {
               get { return _dateModified; }
           }

public string Changes
           {
               get { return _changes; }
           }

public string Issues { get; set; }
       }

[AttributeUsage(AttributeTargets.Assembly)]
       public class SupportsWhatsNewAttribute : Attribute
       {
       }
   }

2.对VectorClass和其成员使用自定义特性

[assembly: SupportsWhatsNew]

namespace VectorClass
   {
       [LastModified("14 Feb 2010", "IEnumerable interface implemented " +
                                    "So Vector can now be treated as a collection")]
       [LastModified("10 Feb 2010", "IFormattable interface implemented " +
                                    "So Vector now responds to format specifiers N and VE")]
       class Vector : IFormattable, IEnumerable
       {
           public double x, y, z;

public Vector(double x, double y, double z)
           {
               this.x = x;
               this.y = y;
               this.z = z;
           }

[LastModified("10 Feb 2010", "Method added in order to provide formatting support")]
           public string ToString(string format, IFormatProvider formatProvider)
           {
               if (format == null)
                   return ToString();
               string formatUpper = format.ToUpper();
               switch (formatUpper)
               {
                   case "N":
                       return "|| " + Norm().ToString() + " ||";
                   case "VE":
                       return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
                   case "IJK":
                       StringBuilder sb = new StringBuilder(x.ToString(), 30);
                       sb.Append(" i + ");
                       sb.Append(y.ToString());
                       sb.Append(" j + ");
                       sb.Append(z.ToString());
                       sb.Append(" k");
                       return sb.ToString();
                   default:
                       return ToString();
               }
           }

public Vector(Vector rhs)
           {
               x = rhs.x;
               y = rhs.y;
               z = rhs.z;
           }

[LastModified("14 Feb 2010", "Method added in order to provide collection support")]
           public IEnumerator GetEnumerator()
           {
               return new VectorEnumerator(this);
           }

public override string ToString()
           {
               return "( " + x + " , " + y + " , " + z + " )";
           }

public double this[uint i]
           {
               get
               {
                   switch (i)
                   {
                       case 0:
                           return x;
                       case 1:
                           return y;
                       case 2:
                           return z;
                       default:
                           throw new IndexOutOfRangeException(
                               "Attempt to retrieve Vector element" + i);
                   }
               }
               set
               {
                   switch (i)
                   {
                       case 0:
                           x = value;
                           break;
                       case 1:
                           y = value;
                           break;
                       case 2:
                           z = value;
                           break;
                       default:
                           throw new IndexOutOfRangeException(
                               "Attempt to set Vector element" + i);
                   }
               }
           }

public static bool operator ==(Vector lhs, Vector rhs)
           {
               if (System.Math.Abs(lhs.x - rhs.x) < double.Epsilon &&
                   System.Math.Abs(lhs.y - rhs.y) < double.Epsilon &&
                   System.Math.Abs(lhs.z - rhs.z) < double.Epsilon)
                   return true;
               else
                   return false;
           }

public static bool operator !=(Vector lhs, Vector rhs)
           {
               return !(lhs == rhs);
           }

public static Vector operator +(Vector lhs, Vector rhs)
           {
               Vector result = new Vector(lhs);
               result.x += rhs.x;
               result.y += rhs.y;
               result.z += rhs.z;
               return result;
           }

public static Vector operator *(double lhs, Vector rhs)
           {
               return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
           }

public static Vector operator *(Vector lhs, double rhs)
           {
               return rhs * lhs;
           }

public static double operator *(Vector lhs, Vector rhs)
           {
               return lhs.x * rhs.x + lhs.y + rhs.y + lhs.z * rhs.z;
           }

public double Norm()
           {
               return x * x + y * y + z * z;
           }

#region enumerator class
           [LastModified("14 Feb 2010", "Class created as part of collection support for Vector")]
           private class VectorEnumerator : IEnumerator
           {
               readonly Vector _theVector;      // Vector object that this enumerato refers to
               int _location;   // which element of _theVector the enumerator is currently referring to

public VectorEnumerator(Vector theVector)
               {
                   _theVector = theVector;
                   _location = -1;
               }

public bool MoveNext()
               {
                   ++_location;
                   return (_location > 2) ? false : true;
               }

public object Current
               {
                   get
                   {
                       if (_location < 0 || _location > 2)
                           throw new InvalidOperationException(
                               "The enumerator is either before the first element or " +
                               "after the last element of the Vector");
                       return _theVector[(uint)_location];
                   }
               }

public void Reset()
               {
                   _location = -1;
               }

}
           #endregion
       }
   }

3.通过反射获取程序集VectorClass和其成员的自定义特性

namespace LookUpWhatsNew
   {
       internal class WhatsNewChecker
       {
           private static readonly StringBuilder outputText = new StringBuilder(1000);
           private static DateTime backDateTo = new DateTime(2010, 2, 1);

private static void Main()
           {
               Assembly theAssembly = Assembly.Load("VectorClass");
               Attribute supportsAttribute =
                   Attribute.GetCustomAttribute(
                       theAssembly, typeof (SupportsWhatsNewAttribute));
               string name = theAssembly.FullName;

AddToMessage("Assembly: " + name);
               if (supportsAttribute == null)
               {
                   AddToMessage(
                       "This assembly does not support WhatsNew attributes");
                   return;
               }
               else
               {
                   AddToMessage("Defined Types:");
               }

Type[] types = theAssembly.GetTypes();
               foreach (Type definedType in types)
                   DisplayTypeInfo(definedType);

MessageBox.Show(outputText.ToString(),
                               "What\'s New since " + backDateTo.ToLongDateString());
               Console.ReadLine();
           }

private static void DisplayTypeInfo(Type type)
           {
               // make sure we only pick out classes
               if (!(type.IsClass))
                   return;
               AddToMessage("\nclass " + type.Name);

Attribute[] attribs = Attribute.GetCustomAttributes(type);
               if (attribs.Length == 0)
                   AddToMessage("No changes to this class");
               else
                   foreach (Attribute attrib in attribs)
                       WriteAttributeInfo(attrib);

MethodInfo[] methods = type.GetMethods();
               AddToMessage("CHANGES TO METHODS OF THIS CLASS:");
               foreach (MethodInfo nextMethod in methods)
               {
                   object[] attribs2 =
                       nextMethod.GetCustomAttributes(
                           typeof (LastModifiedAttribute), false);
                   if (attribs2 != null)
                   {
                       AddToMessage(
                           nextMethod.ReturnType + " " + nextMethod.Name + "()");
                       foreach (Attribute nextAttrib in attribs2)
                           WriteAttributeInfo(nextAttrib);
                   }
               }
           }

private static void WriteAttributeInfo(Attribute attrib)
           {
               LastModifiedAttribute lastModifiedAttrib =
                   attrib as LastModifiedAttribute;
               if (lastModifiedAttrib == null)
                   return;

// check that date is in range
               DateTime modifiedDate = lastModifiedAttrib.DateModified;
               if (modifiedDate < backDateTo)
                   return;

AddToMessage("  MODIFIED: " +
                            modifiedDate.ToLongDateString() + ":");
               AddToMessage("    " + lastModifiedAttrib.Changes);
               if (lastModifiedAttrib.Issues != null)
                   AddToMessage("    Outstanding issues:" +
                                lastModifiedAttrib.Issues);
           }

private static void AddToMessage(string message)
           {
               outputText.Append("\n" + message);
           }
       }
   }

来源:https://www.cnblogs.com/afei-24/p/6867986.html

标签:C#,反射,Reflection
0
投稿

猜你喜欢

  • tk.Mybatis 插入数据获取Id问题

    2023-07-01 22:03:13
  • mybatis教程之resultmap_动力节点Java学院整理

    2022-09-05 22:38:37
  • c# 制作gif的四种方法

    2023-03-17 20:01:08
  • 使用C#调用系统API实现内存注入的代码

    2021-12-01 00:25:59
  • java list随机抽取元素的案例

    2023-12-22 22:21:59
  • JAVA与SQL 中的null与NULL解析

    2023-06-23 11:51:18
  • SpringBoot整合Mybatis与thymleft实现增删改查功能详解

    2023-01-06 00:22:59
  • Android Fragment+FragmentTabHost组件实现常见主页面(仿微信新浪)

    2023-10-20 10:00:50
  • 基于C语言string函数的详解

    2023-06-28 05:33:25
  • java 定时同步数据的任务优化

    2021-09-18 19:48:22
  • Spring Validation方法实现原理分析

    2023-09-04 17:11:55
  • 关于EntityWrapper的in用法

    2023-11-29 09:02:11
  • Springboot项目引入druid安装部署使用教程

    2023-07-28 01:39:25
  • android中Bitmap的放大和缩小实例代码

    2021-10-01 13:23:28
  • Android使用多线程进行网络聊天室通信

    2022-05-11 18:56:36
  • Android启动页出现白屏、黑屏的解决方案

    2022-08-23 21:11:52
  • Java将Exception信息转为String字符串的方法

    2022-12-01 08:39:35
  • C#调用易语言写的Dll文件方法

    2023-07-21 01:56:10
  • C# 如何调用C++ dll string类型返回

    2023-01-31 02:27:55
  • C#服务端图片打包下载实现代码解析

    2023-01-26 07:36:23
  • asp之家 软件编程 m.aspxhome.com