千家信息网

C#反射怎么实现

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,本篇内容介绍了"C#反射怎么实现"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!C#反射技术主要基于S
千家信息网最后更新 2025年02月02日C#反射怎么实现

本篇内容介绍了"C#反射怎么实现"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

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.yisu.com/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#反射怎么实现"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0