1. 程式人生 > >C#之反射

C#之反射

col .com new end 之間 除了 console 單例 getc

反射是給你一個程序集dll,可以反射出其中的所有元數據metadata,包括字段、屬性、方法等,反射最重要的重要就是利用反射創建對象,從而達到層與層之間的低耦合效果。IOC依賴註入容器就是反射典型的應用場景,包過MVC、ORM都用到了反射。反射在我們程序設計中是無處不在的,只不過現在有很多第三方的框架、組件幫我們封裝好了,有時候感覺不到反射的應用,下面我們就深入了解一下反射。

1.反射創建對象

1//常規創建對象的方法 
IDBHelper iDBHelper = new MySqlHelper(); 2 iDBHelper.Query(); 3 //這種代碼我們應該經常寫 使用接口仍然避免不了對MySqlHelper所在類的dll的依賴
Assembly assembly = Assembly.Load("MySql");//1.加載程序集  註意:一定要在主項目中添加該類庫的引用 該dll要和exe文件在同一個文件夾中
                    Type type = assembly.GetType("MySql.MySqlHelper");//2.獲取程序集中指定的對象類型
                    IDBHelper iDBHelper = (IDBHelper)Activator.CreateInstance(type);//3.創建對象
                    iDBHelper.Query();

                    
//反射獲取該類型中的所有公共方法 foreach (var t in type.GetMethods()) { Console.WriteLine(t.Name); } //反射獲取該類型中的所有公共屬性 foreach (var t in type.GetProperties()) { Console.WriteLine(t.Name); }

2.上面只是說明了反射可以創建無參構造函數,反射還可以創建帶參數的構造函數。

 public class MySqlHelper : IDBHelper
    {
       
        public string Name { get; set; }
        protected int Age { get; set; }
        
        public  MySqlHelper()
        {
            Console.WriteLine("{0}被構造-無參",this.GetType().Name);
        }
        public MySqlHelper(string Name)
        {
            this.Name = Name;
            Console.WriteLine("帶有一個參數構造被構建");
        }
        public MySqlHelper(string Name, int Age)
        {
            this.Name = Name;
            this.Age = Age;
            Console.WriteLine("帶有兩個參數構造函數別構建");
        }
        public void Query()
        {
            Console.WriteLine("{0}.Query",this.GetType().Name);
        }
        protected void Fun()
        {
        }
    }

#region 反射創建對象-有參構造函數
{
Assembly assembly = Assembly.Load("MySql");
Type type = assembly.GetType("MySql.MySqlHelper");
//遍歷所有公共構造函數
foreach (var t in type.GetConstructors())
{
Console.WriteLine("構造函數名:"+t.Name);
foreach (var p in t.GetParameters())
{
Console.WriteLine(p.ParameterType);
}
}
IDBHelper dBHelper = (IDBHelper)Activator.CreateInstance(type);
IDBHelper dBHelper2 = (IDBHelper)Activator.CreateInstance(type,new object[] { "張三"});
IDBHelper dBHelper3 = (IDBHelper)Activator.CreateInstance(type,new object[] { "李四",18});
}
#endregion

 

運行結果:

技術分享圖片

4.我們都知道當我們在程序設計的時候運用到了單例模式,該對象只可能被實例化一次。。但是。。。運用反射可以 破壞單例模式 。 即反射可以調用私有構造函數從而創建對象。

 public class SqlServerHelper:IDBHelper
    {
        //public SqlServerHelper()
        //{
        //  Console.WriteLine("{0}被構造",this.GetType().Name);
        // }
        private SqlServerHelper()
        {
            Console.WriteLine("無參構造函數被創建");
        }
        public void Query()
        {
            Console.WriteLine("{0}被構造",this.GetType().Name);
        }
    }
 public class SqlServerHelper:IDBHelper
    {
        //public SqlServerHelper()
        //{
        //  Console.WriteLine("{0}被構造",this.GetType().Name);
        // }
        private SqlServerHelper()
        {
            Console.WriteLine("無參構造函數被創建");
        }
        public void Query()
        {
            Console.WriteLine("{0}被構造",this.GetType().Name);
        }
    }


 #region 反射破壞單例  調用私有構造函數創建對象
                {
                    Console.WriteLine("反射調用私有構造函數創建對象");
                    Assembly assembly = Assembly.Load("SqlServer");
                    Type type = assembly.GetType("SqlServer.SqlServerHelper");
                    IDBHelper dBHelper = (IDBHelper)Activator.CreateInstance(type,true);//可以調用私有構造函數
                    dBHelper.Query();
                }
                #endregion

程序結果:

技術分享圖片

5.反射創建泛型對象

 public class GenericClass<T,S>
    {
        public GenericClass()
        {
            Console.WriteLine("泛型對象被創建"+typeof(T)+typeof(S));
        }
       
    }
 #region 反射創建泛型對象
                {
                    Console.WriteLine("反射創建泛型對象");
                    Assembly assembly = Assembly.Load("MySql");
                    //Type type = assembly.GetType("MySql.GenericClass");
                    Type type = assembly.GetType("MySql.GenericClass`2");//泛型類獲取對象
                    Type genericType = type.MakeGenericType(new Type[] { typeof(int),typeof(string)});
                    object genericObject = Activator.CreateInstance(genericType);
                   
                }
                #endregion

程序結果:

技術分享圖片

反射除了創建創建對象 還可以調用方法,獲取字段、屬性功能

C#之反射