2014年1月19日 星期日

C# - Reflection 反映

反映 (Reflection) 會提供 Type 型別的物件,用來描述組件、模組和型別。 您可以使用反映來動態建立型別的執行個體、將型別繫結至現有物件,或從現有物件取得型別,並叫用其方法或存取其欄位和屬性。 如果您在程式碼中使用屬性,反映可讓您存取這些屬性。 如需詳細資訊,請參閱使用屬性擴充中繼資料。

反射提供了封裝程式集、模組和類型的物件。
開發者可以使用反射動態地創建類型的實例,將類型綁定到現有物件(這個不會),或從現有物件中獲取類型。然後,可以調用類型的方法或訪問其欄位和屬性。

namespace TestReflection
{
    class Program
    {
        static void Main(string[] args)
        {
            object A = new AX();
            object B = new AXzhz();
            new TestObjectType().TestObjectTypeNow(A, B);
        }
    }

    class AX { }
    class AXzhz { }
    class TestObjectType
    {
        internal void TestObjectTypeNow(object A, object B)
        {
            Type tpA = A.GetType();
            Type tpB = B.GetType();
            Console.WriteLine(tpA.FullName);
            Console.WriteLine(tpB.FullName);
            Console.ReadLine();
        }
    }

}

獲得的Type實例的用途:

  • 獲得類名:如上面例子的FullName屬性,返回TestReflection.AX

這個也比較噁心,直接用A.ToString();返回的也是這個結果.

  • 創建該類的對象.你首先通過ⅰ來獲得類名AX

AX ax = (AX)Activator.CreateInstance(tpA);

  • 獲得物件所屬類的相關資訊

通過tpA的相關屬性,來得到該類的相關資訊.
通過一個物件實例,可以獲得包含這個物件實例的類的Assembly,進而獲得整個Assembly的資訊。

namespace TestReflection
{
    class Program
    {
        public static void Main(string[] args)
        {
            object A = new AX();

            //獲取物件所屬的Assembly的所有類的基本資訊
            new TestObjectType().TestObjectTypeNow(A);
        }
    }

    class AX
    {
        internal int kkkkkkkk = 0;
        public int ooooooooo;
        private int property;

        public int Property
        {
            get { return property; }
            set { property = value; }
        }

        public void A()
        {
            Console.WriteLine("AX's function!~");
        }
    }

    class AXzhz { }

    class TestObjectType
    {
        internal void TestObjectTypeNow(object A)
        {
            Type tpA = A.GetType();
            Assembly assembly = tpA.Assembly;
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                Console.WriteLine("【類名】" + type.FullName);
                ConstructorInfo[] myconstructors = type.GetConstructors();
                Show(myconstructors);
                FieldInfo[] myfields = type.GetFields();
                Show(myfields);
                MethodInfo[] myMethodInfo = type.GetMethods();
                Show(myMethodInfo);
                PropertyInfo[] myproperties = type.GetProperties();
                Show(myproperties);
            }

            Console.ReadLine();
        }

        //顯示陣列的基本資訊
        public void Show(object[] os)
        {
            foreach (object var in os)
            {
                Console.WriteLine(var.ToString());
            }

            Console.WriteLine("----------------------------------");
        }
    }

}

實現抽象工廠的基礎,也是實現抽象工廠的核心技術,通過它,可以動態創建一個你想要的物件。下面的例子是演示如何動態創建ChineseName或EnglishName的實例:


namespace TestReflection
{
    class AXzhz_sReflectionExample
    {
        public static void Main()
        {
            IName name = AbstractFactory.GetName();
            name.ShowName();
        }
    }

    public class AbstractFactory
    {
        public static IName GetName()
        {
            //s的值以後從Web.config動態獲取
            //s賦值為:TestReflection.EnglishName,將顯示英文名
            string s = "TestReflection.ChineseName";
            IName name = (IName)Assembly.Load("TestReflection").CreateInstance(s);
            return name;
        }
    }

    //聲明一個介面,它有一個顯示"名字"的功能
    public interface IName
    {
        void ShowName();
    }

    //實現介面,顯示中國名字
    public class ChineseName : IName
    {
        public void ShowName()
        {
            Console.WriteLine("我叫AX!");
            Console.ReadLine();
        }
    }

    //實現介面,顯示英國名字
    public class EnglishName : IName
    {
        void IName.ShowName()
        {
            Console.WriteLine("My name is AXzhz!");
            Console.ReadLine();
        }
    }

}


可以使用下面的方法了解都用到了哪些Assembly,得到Assembly裡的資訊:

namespace TestReflection
{
    class ShowAllAssembly
    {
        public static void Main()
        {
            //獲得解決方案的所有Assembly
            Assembly[] AX = AppDomain.CurrentDomain.GetAssemblies();

            //遍歷顯示每個Assembly的名字
            foreach (object var in AX)
            {
                Console.WriteLine("Assembly的名字:" + var.ToString());
            }

            //使用一個已知的Assembly名稱,來創建一個Assembly
            //通過CodeBase屬性顯示最初指定的程式集的位置
            Console.WriteLine("最初指定的程式集TestReflection的位置:" + Assembly.Load("TestReflection").CodeBase);
            Console.ReadLine();
        }
    }
}



打完收工

-雲遊山水為知已逍遙一生而忘齡- 電腦神手

沒有留言:

張貼留言