C# 反射 (Reflect)
# C# 反射 (Reflect)
1.基本內(nèi)容
我們可以使用反射動態(tài)地創(chuàng)建類型的實(shí)例,將類型綁定到現(xiàn)有對象,或從現(xiàn)有對象中獲取類型。然后,可以調(diào)用類型的方法或訪問其字段和屬性。
最基本的調(diào)用:
Assembly assembly = Assembly.Load("DB.SqlServer");//將加載dll Type type = assembly.GetType("DB.SqlServer.SqlServerHelper");//得到DLL 中的SqlServerHelper 類 object obj = Activator.CreateInstance(type);//創(chuàng)建類的實(shí)例 SqlServerHelper helper = (SqlServerHelper)obj;//將創(chuàng)建的Object 對象轉(zhuǎn)換為SqlServerHelper對象 helper.Query();//調(diào)用對象的方法2.創(chuàng)建對象
工廠方法
反射的一個(gè)應(yīng)用場景是,當(dāng)我們開發(fā)的程序的數(shù)據(jù)庫是可能變化時(shí),就會用到反射,入下述代碼:
//這是一個(gè)DB接口層 namespace DB.Interface {public interface IDBHelper{void Query();} } //這是SqlServer數(shù)據(jù)庫的操作層 namespace DB.SqlServer {public class SqlServerHelper : IDBHelper//繼承自DB接口層{public void Query(){Console.WriteLine("我是{0}", typeof(SqlServerHelper));}} } //這是MySql數(shù)據(jù)庫的操作層 namespace DB.MySql {public class MySqlHelper : IDBHelper//繼承自DB接口層{public void Query(){Console.WriteLine("我是{0}", typeof(MySqlHelper));}} }然后我們會建造一個(gè)工廠類,專門用于生產(chǎn)對象:
//這是工廠層 public class Factory {static string IDBHelperConfig = System.Configuration.ConfigurationManager.AppSettings["IDBHelperConfig"];static string DllName = IDBHelperConfig.Split(',')[0];static string TypeName = IDBHelperConfig.Split(',')[1];public static IDBHelper CreateDBHelper(){Assembly assembly = Assembly.Load(DllName);//將加載dll Type type = assembly.GetType(TypeName);//得到DLL 中的SqlServerHelper 類object obj = Activator.CreateInstance(type);//創(chuàng)建類的實(shí)例return (IDBHelper)obj;//將創(chuàng)建的Object 對象轉(zhuǎn)換為IDBHelper對象 并返回} }然后在app.config 文件中添加配置:
<appSettings><!--這是配置字符串--><add key="IDBHelperConfig" value="DB.SqlServer,DB.SqlServer.SqlServerHelper"/> </appSettings>最后在調(diào)用層面調(diào)用:
//這是調(diào)用 IDBHelper dbHelper = Factory.CreateDBHelper(); dbHelper.Query();這樣當(dāng)數(shù)據(jù)庫從SqlServer 修改為 MySql 時(shí),我們只需要修改app.config中的配置字符串即可,而不需要修改源代碼,這樣有利于我們程序的維護(hù),與穩(wěn)定。
帶參數(shù)對象創(chuàng)建
基礎(chǔ)類
namespace Model {public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public Person(int id){Console.WriteLine("我是有1個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,無參數(shù)構(gòu)造函數(shù)");}} }有參數(shù)的構(gòu)造函數(shù)調(diào)用方式:
Assembly assembly = Assembly.Load("Model"); Type personType = assembly.GetType("Model.Person"); //調(diào)用帶1個(gè)參數(shù)的構(gòu)造函數(shù) object obj = Activator.CreateInstance(personType, new object[] { 123 }); //調(diào)用帶2個(gè)參數(shù)的構(gòu)造函數(shù) object obj2 = Activator.CreateInstance(personType, new object[] { 123, "Oliver" }); //調(diào)用帶3個(gè)參數(shù)的構(gòu)造函數(shù) object obj3 = Activator.CreateInstance(personType, new object[] { 123, "Oliver", DateTime.Now });調(diào)用私有構(gòu)造函數(shù)
Assembly assembly = Assembly.Load("Model"); Type personType = assembly.GetType("Model.Person"); //調(diào)用私有函數(shù) object obj4 = Activator.CreateInstance(personType,true);泛型類創(chuàng)建
基礎(chǔ)類
namespace Model {//添加泛型類public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型類的構(gòu)造函數(shù)!");}public T GetT(){return default(T);}} }通過反射的方法創(chuàng)建泛型對象
Assembly assembly = Assembly.Load("Model"); Type gennericClassType = assembly.GetType("Model.GenericClass`1");//如果是一個(gè)泛型需要在后面添加`1,否則取出來的時(shí)NULL Type newGennericClassType = gennericClassType.MakeGenericType(new Type[] { typeof(int) }); var obj = Activator.CreateInstance(newGennericClassType);注意反射泛型類的時(shí)候GetType方法傳入的類名稱,需要在后面添加相應(yīng)的泛型個(gè)數(shù)。下面這句代碼也相應(yīng)的說明這個(gè)情況。
//輸出的值也會有一個(gè)`1 Console.WriteLine(typeof(GenericClass<int>));//輸出:Model.GenericClass`1[System.Int32]3.調(diào)用方法
基礎(chǔ)類
namespace Model {public class Person{public int Id { get; set; }public string Name { get; set; }public DateTime CreateDate { get; set; }public string Memo;//字段public Person(int id){Console.WriteLine("我是有1個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;}public Person(int id, string name){Console.WriteLine("我是有2個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;this.Name = name;}public Person(int id, string name, DateTime createDate){Console.WriteLine("我是有3個(gè)參數(shù)的構(gòu)造函數(shù)!");this.Id = id;this.Name = name;this.CreateDate = createDate;}private Person(){Console.WriteLine("我是私有的,無參數(shù)構(gòu)造函數(shù)");}//帶有返回值的無參方法public DateTime Show(){Console.WriteLine("我是帶有返回值的無參方法。");return DateTime.Now;}//帶有參數(shù)的方法public void Show2(int i){Console.WriteLine("我是Show2(int i).i=" + i);}//重載方法public void Show3(int i){Console.WriteLine("我是Show3(int i).i=" + i);}//重載方法public void Show3(string s){Console.WriteLine("我是Show3(string s).s=" + s);}//私有方法private void Show4(){Console.WriteLine("我是私有方法");}//靜態(tài)方法public static void Show5(){Console.WriteLine("我是靜態(tài)方法");}} }無參方法
Assembly assembly = Assembly.Load("Model");//加載dll Type personType = assembly.GetType("Model.Person");//得到類 object objPerson = Activator.CreateInstance(personType, true);//創(chuàng)建對象 //調(diào)用 有返回值 無參數(shù)的方法 MethodInfo show = personType.GetMethod("Show");//找到方法 DateTime dt = (DateTime)(show.Invoke(objPerson, new object[] { }));//調(diào)用,并接收返回值帶參數(shù)方法
//調(diào)用 帶有參數(shù)的方法 MethodInfo show2 = personType.GetMethod("Show2"); show2.Invoke(objPerson, new object[] { 123 });重載方法
//調(diào)用 重載方法1 MethodInfo show3 = personType.GetMethod("Show3", new Type[] { typeof(int) }); show3.Invoke(objPerson, new object[] { 234 });//調(diào)用 重載方法2 MethodInfo show3_1 = personType.GetMethod("Show3", new Type[] { typeof(string) }); show3_1.Invoke(objPerson, new object[] { "ABC" });私有方法
//調(diào)用私有方法 MethodInfo show4 = personType.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic); show4.Invoke(objPerson, new object[] { });靜態(tài)方法(兩種形式)
//調(diào)用靜態(tài)方法 MethodInfo show5 = personType.GetMethod("Show5"); show5.Invoke(objPerson, new object[] { });//類似于 實(shí)例調(diào)用 show5.Invoke(null, new object[] { });//類似于直接通過類名稱調(diào)用調(diào)用泛型類的泛型方法
基礎(chǔ)類
namespace Model {//添加泛型類public class GenericClass<T>{public GenericClass(){Console.WriteLine("我是泛型類的構(gòu)造函數(shù)!");}public T GetT<S>(T t, S s){Console.WriteLine("我是泛型類中的泛型方法!t_type:{0}, t_value:{1}\ts_type:{2}, s_value:{3}", typeof(T), t, typeof(S), s);return t;}} }調(diào)用GenericClass類的GetT方法
Assembly assembly = Assembly.Load("Model"); Type genericClassType = assembly.GetType("Model.GenericClass`1");//`1 千萬別忘記 Type newGenericClassType = genericClassType.MakeGenericType(new Type[] { typeof(int) }); object obj= Activator.CreateInstance(newGenericClassType);//創(chuàng)建對象 MethodInfo methodInfo = newGenericClassType.GetMethod("GetT"); MethodInfo newMethodInfo = methodInfo.MakeGenericMethod(new Type[] { typeof(string) }); newMethodInfo.Invoke(obj, new object[] { 123, "Oliver" });//輸出:我是泛型類中的泛型方法!t_type:System.Int32, t_value:123 s_type:System.String, s_value:Oliver4.get set 屬性、字段
屬性操作
Person p = new Person(1, "Oliver", DateTime.Now); Type t = p.GetType(); PropertyInfo propertyInfo = t.GetProperty("Id"); Console.WriteLine(propertyInfo.GetValue(p));//獲取 屬性的值。輸出 1 propertyInfo.SetValue(p,123);//獲取 屬性的值 Console.WriteLine(propertyInfo.GetValue(p));//設(shè)置 屬性的值。輸出 123//遍歷屬性 foreach (var prop in t.GetProperties()) {Console.WriteLine("{0}.{1}={2}", typeof(Person), propertyInfo.Name, prop.GetValue(p));/*輸出:Model.Person.Id=123Model.Person.Id=OliverModel.Person.Id=2018/8/8 22:15:09*/ }字段操作
Person p = new Person(1, "Oliver", DateTime.Now); Type t = p.GetType(); FieldInfo fieldInfo = t.GetField("Memo"); Console.WriteLine(fieldInfo.GetValue(p));//獲取 屬性的值。輸出 空字符串 fieldInfo.SetValue(p, "自律給我自由");//獲取 屬性的值 Console.WriteLine(fieldInfo.GetValue(p));//設(shè)置 屬性的值。輸出 自律給我自由轉(zhuǎn)載于:https://www.cnblogs.com/haowuji/p/9446118.html
總結(jié)
以上是生活随笔為你收集整理的C# 反射 (Reflect)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [NOI2005]维护数列 恶心到毁天
- 下一篇: js传真实地址 C:\fakepath