溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C#反射怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-04-13 10:07:50 來源:億速云 閱讀:186 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“C#反射怎么實(shí)現(xiàn)”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

C#反射技術(shù)主要基于System.Type類和System.Reflection.Assemble類,通過Type類可以訪問關(guān)于任何數(shù)據(jù)類型的信息,Assemble類用于訪問給定程序集的相關(guān)信息,或把這個(gè)程序集加載到程序中。

一.System.Type類

Type類是一個(gè)抽象類。只要實(shí)例化了一個(gè)Type對(duì)象,實(shí)際上就實(shí)例化了Type的一個(gè)派生類。盡管一般情況下派生類只提供各種Type方法和屬性的不同重載,但是這些方法和屬性返回對(duì)應(yīng)數(shù)據(jù)類型的正確數(shù)據(jù),Type有與每種數(shù)據(jù)類型對(duì)應(yīng)的派生類。它們一般不添加新的方法或?qū)傩?br/>通常,獲取指向任何給定的Type引用有三種常用方式:

  • *使用typeof運(yùn)算符,這個(gè)運(yùn)算符的參數(shù)是類型的名稱,但不放在引號(hào)中:

Type t =typeof(double);
  • *使用GetType()方法,所以類都會(huì)從System.Object繼承這個(gè)方法:

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

在一個(gè)變量上調(diào)用GetType()方法,返回的Type對(duì)象只與該數(shù)據(jù)類型相關(guān),不包含該類型實(shí)例的任何信息。

  • *調(diào)用Type類的靜態(tài)方法GetType():

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

Type是很多反射功能的入口,它實(shí)現(xiàn)很多方法和屬性,可用的屬性都是只讀的:可以使用Type確定數(shù)據(jù)的類型,但不能使用它修改該類型。

1.Type屬性

由Type實(shí)現(xiàn)的屬性分為3類。

  • *包含與類相關(guān)的各種名稱的字符串:

    • Name:數(shù)據(jù)類型名

    • FullName:數(shù)據(jù)類型的完全限定名(包含名稱空間)

    • Namespace:在其中定義數(shù)據(jù)類型的名稱空間名

  • *獲取Type對(duì)象的引用的屬性:

    • BaseType:該對(duì)象的直接基本類型

    • UnderlyingSystemType:該Type在.NET運(yùn)行庫中映射到的類型

  • *布爾屬性

    • IsAbstract,IsArray,IsClass,IsEnum等判斷Type是什么類型的屬性。

2.方法

System.Type的大多數(shù)方法都用于獲取對(duì)應(yīng)數(shù)據(jù)類型的成員信息:構(gòu)造函數(shù),屬性,方法和事件等。它有許多方法,但它們都有相同的模式。例如,獲取數(shù)據(jù)類型的方法的信息:GetMethod()和GetMethods()。GetMethod()方法返回MethodInfo對(duì)象的一個(gè)引用,其中包含一個(gè)指定方法的細(xì)節(jié)信息;而GetMethods()返回這種引用的一個(gè)數(shù)組。

C#反射怎么實(shí)現(xiàn)

二.Assembly類

Assembly類允許訪問給定程序集的元數(shù)據(jù),它也包含可以加載和執(zhí)行程序集(假定該程序集是可執(zhí)行的)的方法。與Type類一樣,Assembly類包含非常多的方法和屬性,這里只介紹與特性(//kemok4.com/article/244250.htm)有關(guān)的成員,其它成員可以去MSDN(https://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.100).aspx)查看。

C#反射怎么實(shí)現(xiàn)

C#反射怎么實(shí)現(xiàn)

C#反射怎么實(shí)現(xiàn)

在使用Assembly實(shí)例做一些工作前,需要把相應(yīng)的程序集加載到正在運(yùn)行的進(jìn)程中。可以使用靜態(tài)方法Assembly.Load()或Assembly.LoadFrom()。Load()方法的參數(shù)程序集的名稱,運(yùn)行庫會(huì)在各個(gè)位置上搜索該程序集,這些位置包括本地目錄和全局程序集緩存。而LoadFrom()方法的參數(shù)是程序集的完整路徑名,它不會(huì)在其它位置搜索該程序集:

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

這兩個(gè)方法都有許多其它重載版本。

1.獲取在程序集中定義的類型的詳細(xì)信息

Assembly類調(diào)用GetType()方法可以獲得相應(yīng)程序集中定義的所有類型的詳細(xì)信息,它返回一個(gè)包含所有類型的詳細(xì)信息的System.Type引用數(shù)組:

    Type[] types = assembly1.GetType();

    foreach(Type t in types)
    {

    }

2.獲取自定義特性的詳細(xì)信息

如果需要確定程序集關(guān)聯(lián)了什么自定義特性,就需要調(diào)用Attribute類的一個(gè)靜態(tài)方法GetCustomAttributes():

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

GetCustomAttributes方法用于獲取程序集的特性,他有兩個(gè)重載方法:如果在調(diào)用它時(shí),除了程序集的引用外,沒有其它參數(shù),該方法就會(huì)返回這個(gè)程序集定義的所以自定義特性;如果指定第二個(gè)參數(shù),第二個(gè)參數(shù)表示特性類的一個(gè)Type對(duì)象,GetCustomAttributes方法返回指定特性類型的特性數(shù)組。
所有的特性都作為一般的Attribute引用來獲取。如果需要調(diào)用為自定義特性定義的任何方法或?qū)傩?,就需要把這些引用顯示轉(zhuǎn)換為自定義特性類。
如果要獲得與方法,構(gòu)造函數(shù)和字段等的特性,就需要調(diào)用MethodInfo,ConstructorInfo,FieldInfo等類的GetCustomAttributes()方法。
下面通過一個(gè)例子演示,自定義特性和反射

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.對(duì)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#反射怎么實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI