C#反射(Reflection)详解

目录
  • 一.System.Type类
    • 1.Type属性
    • 2.方法
  • 二.Assembly类
  • 1.获取在程序集中定义的类型的详细信息
    • 2.获取自定义特性的详细信息
      • 1.编写自定义特性
      • 2.对VectorClass和其成员使用自定义特性
      • 3.通过反射获取程序集VectorClass和其成员的自定义特性

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()返回这种引用的一个数组。

二.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)查看。

在使用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);
            }
        }
    }

到此这篇关于C#反射(Reflection)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#反射机制介绍

    先看下面一个动物点名系统的简单例子: 有一个Animal的抽象动物父类,里面定义了Name.Age两个属性和一个Shout()方法,Animal类定义如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Animal { /// <summary> /// 抽象父类 /// </sum

  • C#反射使用方法过程及步骤

    C#反射使用方法过程及步骤,供大家参考,具体内容如下 1. 定义要访问类的全名 2. 获取该类的类型 3. 实例化该类 4. 获取该类的字段.属性,方法 5. 设置该字段或属性内容,或调用其方法 从而达到使用字符串访问相应类的目的. 示例: 1. 根据窗口类的名称,产生一个新的窗口,相当于new 窗口类 //1. 定义窗口类名称:(窗口类的字符串名字,需要全路径名,否则获取不到TYPE) string customClassName = @"IBAutoDeal.IBDealForms.&quo

  • c# 反射用法及效率对比

    反射实例化类 public class Person { public string Name { get; set; } public Person(string name) { this.Name = name; } public string Say(string msg) { return $"{Name}: {msg}"; } } class Program { // 测试次数 const int count = 10000000; static void Main(stri

  • C#反射(Reflection)对类的属性get或set值实现思路

    近段时间,有朋友叫Insus了解一下反射(Reflection)方面的知识,反射提供了封装程序集.模块和类型的对象(Type类型).可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性.如果代码中使用了属性,可以利用反射对它们进行访问. 下面的例子,是Insus练习对一个类别的属性进行set和get值. 首先写一个类,再写一个可读写的属性: 复制代码 代码如下: using System; using System.Collections.Ge

  • 详解C# 反射(Reflection)

    C# 反射(Reflection) 反射指程序可以访问.检测和修改它本身状态或行为的一种能力. 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象. 您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 优缺点 优点: 1.反射提高了程序的灵活性和扩展性. 2.降低耦合性,提高自适应能力. 3.它允许程序创建和控制任何类的对象,无需提前硬编码目标类. 缺点: 1.性能问题:使用反射基本

  • C# 反射(Reflection)的用处分析

    乱侃 作为一名新手,一直没有勇气去写一篇分享.原因有很多:诸如:自己水平有限.语言表达不准确.写出的东西没有一点技术点被人嘲笑.今天在公司听了内部员工的一个分享,其中最重要的一点是:提升自身水平的最佳的途径就是--交流.不管你是通过什么途径,交流也好.整理成文字分享也好等等都是很好的方式.故此,今天献丑写一篇自己的心得分享,欢迎各路大神的指教!    需求背景 今天接到的需求里面有个这样的需求,如下图所示,需要打印出如Excel内容呈现的单据.     动手操作第一版本 而为了实现这个业务需要涉

  • C#反射(Reflection)详解

    目录 一.System.Type类 1.Type属性 2.方法 二.Assembly类 1.获取在程序集中定义的类型的详细信息 2.获取自定义特性的详细信息 1.编写自定义特性 2.对VectorClass和其成员使用自定义特性 3.通过反射获取程序集VectorClass和其成员的自定义特性 C#反射技术主要基于System.Type类和System.Reflection.Assemble类,通过Type类可以访问关于任何数据类型的信息,Assemble类用于访问给定程序集的相关信息,或把这个

  • Swift进阶教程Mirror反射示例详解

    目录 元类型与.self AnyObject AnyClass Any type(Of:) self self在方法里面的作用 Self Swift Runtime Mirror Mirror的基本用法 Mirror的简单应用-JSON解析 Mirror源码解析 Enum Metadata探索 还原TargetEnumMetadata 还原TargetEnumDescriptor 相对偏移指针 打印枚举中的属性 Struct Metadata探索 获取结构体的属性 swift_getTypeBy

  • Java中的反射机制详解

    Java中的反射机制详解 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 看概念很晕的,继续往下

  • Java 反射机制详解及实例

    Java 反射机制详解及实例 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧!            一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高

  • Java动态代理和反射机制详解

    反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). 静态代理 预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理 动态代理 代理类在程序运行时创建的代理方式.也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的"指示"动态生成的. 动态代理比

  • Java反射技术详解及实例解析

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术.Hook技术等必不可少的! 一.基本反射技术   1.1 根据一个字符串得到一个类 getClass方法 String nam

  • Go语言基础反射示例详解

    目录 概述 语法 一.基本操作 二.修改目标对象 三.动态调用方法 总结 示例 概述 在程序运行期对程序动态的进行访问和修改 reflect godoc: https://golang.org/pkg/reflect/ reflect包有两个数据类型: Type:数据类型 [reflect.TypeOf():是获取Type的方法] Value:值的类型[reflect.ValueOf():是获取Value的方法] 语法 一.基本操作 获取变量类型 func TypeOf(i interface{

  • Java基础篇之反射机制详解

    目录 1.反射概述 1.1什么是反射 1.2.反射能干什么 2.解剖类 2.1反射构造方法 2.1.1反射无参的构造函数 2.1.2反射“一个参数”的构造函数 2.1.3反射“多个参数”的构造函数 2.1.4反射“私有”的构造函数 2.1.5反射得到类中所有的构造函数 2.2反射类中的方法 2.3反射类中的属性字段 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1.使用new关键字:这是我们最常见的也是最简单的创建对象的方式

  • Go REFLECT Library反射类型详解

    目录 一.反射概述 二.反射类型对象 基本数类型的 反射类型对象 引用数据类型的 反射类型对象 结构体的 反射类型对象 指针的 反射类型对象 一.反射概述 反射是指程序在运行期间对程序本身进行访问和修改的能力.程序在编译过程中变量会被转换为内存地址,变量名不会被编译器写入到可执行部分.在程序运行时程序无法获取自身的信息. 在静态语言中如 Java 可以在程序编译期将变量的反射信息,如字段名称.类型等信息整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取类型的反射信息,并

  • Java 反射机制详解及实例代码

    Java反射详解 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象获得完整的包名和类名 package Reflect; /** * 通过一个对象获得完整的包名和类名 * */ class Demo{ //other codes... } class hello{ public static void main(String[] args) {

随机推荐