最近仔細學習了一下C#的反射機制,希望能和大家分享。 提到反射我想大家都不陌生,反射提供了封裝程式集、模組和類型的對象( Type 類型)。可以使用反射動態建立類型的執行個體,將類型綁定到現有對象,或從現有對象擷取類型並調用其方法或訪問其欄位和屬性,所在命名空間using System.Reflection。
反射的作用:
- 1.使用反射可以動態建立類型的執行個體,然後將執行個體再邦定到現有的對象或從現有對象中擷取類型。
- 2.應用程式需要在運行時從某個特定的程式集中載入特定的類型,以建立特定類型的執行個體。
正是因為反射的特性(動態建立執行個體)所以在多個模組之間減少代碼的緊偶合方面,利用反射可以起到了很大的改善。但是反射也有它的弊端,就是要以犧牲效能為代價,而且有些資訊利用反射是無法得到的。在使用時要根據情況進行選擇。我想通過的層次模型大家可能會更明白它的機制。
以上關於反射知識瞭解之後,在通過代碼大家可能會更好的理解反射:
首先在Vs2008中建立一個類型,命名為ReflectDemo類庫。並添加一個名為ReflectTest的類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SKY.ReflectDemo
{
public class ReflectTest : IPerson
{
private string _name;
private int _age;
public string Name { get { return this._name; } set { this._name = value; } }
public int Age { get { return this._age; } set { this._age = value; } }
public ReflectTest(string name, int age)
{
this._name = name;
this._age = age;
}
public string WelcomeInfo(string name)
{
return "welcome come here " + name;
}
public static string WriteStaticInfo(string name)
{
return "welcome come here static" + name;
}
public static string WriteStaticNoParam()
{
return "Static and No parma";
}
public void Show(string info)
{
Console.WriteLine(info);
}
public ReflectTest() { }
public string WriteNoPara()
{
return "你使用的是無參的方法";
}
private string WritePrivate()
{
return "私人類型的方法";
}
#region IPerson 成員
public int Add()
{
return Age;
}
#endregion
}
public interface IPerson
{
/// <summary>
/// 添加對象
/// </summary>
/// <returns></returns>
int Add();
}
}
然後再建立一個用戶端程式:例如clientTestDemo,添加剛剛建立的程式集引用,引用命名空間using System.Reflection
class Program
{
delegate string TestDelegate(string name);
static void Main(string[] args)
{
//*********************引導程式集************************//
//Assembly ass = Assembly.LoadFrom(("SKY.ReflectDemo.dll"));
//Assembly ass=Assembly.GetAssembly(typeof(SKY.ReflectDemo.ReflectTest);
Assembly ass = Assembly.Load("SKY.ReflectDemo");//功能同上
Console.Write(ass.FullName+"\n");
//*********************顯示該dll下所有的類***************//
foreach (Type type in ass.GetTypes())
{
Console.Write(type.Name+"\n");
}
//*********************顯示該dll下指定類**************//
Type itype = ass.GetType("SKY.ReflectDemo.ReflectTest");
Console.Write(itype.Name);
Type itype1 = typeof(SKY.ReflectDemo.ReflectTest);
//********************所有模組***********************//
foreach (Module temp in ass.GetModules())
{
Console.WriteLine(temp.Assembly.FullName);
}
//********************建立該類的執行個體,後面的param為有參建構函式的參數******************//
object[] param = { "test", 30 };//建構函式參數
SKY.ReflectDemo.ReflectTest temp1 = (SKY.ReflectDemo.ReflectTest)Activator.CreateInstance(itype1, param);
// SKY.ReflectDemo.ReflectTest temp1 = (SKY.ReflectDemo.ReflectTest)ass.CreateInstance("SKY.ReflectDemo.ReflectTest");
Console.WriteLine(temp1.WriteNoPara());
//******************************顯示所有的共有方法************************************//
MethodInfo[] methods = itype.GetMethods();
Console.WriteLine("------------------------顯示所有的共有方法-------------------------");
foreach (MethodInfo temp in methods)
{
Console.WriteLine(temp.Name);
}
//******************************顯示特定方法************************************//
Console.WriteLine("------------------------顯示特定方法------------------------------");
MethodInfo method1 = itype.GetMethod("WriteStaticInfo"); //帶參的靜態方法
Console.WriteLine(method1.Name);
object[] param1 = { "使用的是靜態方法" };
string s1 = (string)method1.Invoke(null, param1);
Console.WriteLine("執行後:"+s1+"\n");
MethodInfo method2 = itype.GetMethod("WriteStaticNoParam");//無參靜態方法
Console.WriteLine(method2.Name);
string s2 = method2.Invoke(null, null) as string;
Console.WriteLine("執行後:" + s2 + "\n");
MethodInfo method3 = itype.GetMethod("WelcomeInfo");//帶參的非靜態方法
Console.WriteLine(method3.Name);
object[] param2 = { "使用的是帶有參數的非靜態方法" };
string s3 = (string)method3.Invoke(temp1, param2);
Console.WriteLine("執行後:" + s3 + "\n");
MethodInfo method4 = itype.GetMethod("WriteNoPara");//無參非靜態方法
Console.WriteLine(method4.Name);
string s4 = method4.Invoke(temp1, null) as string;
Console.WriteLine("執行後:" + s4 + "\n");
MethodInfo method5 = itype.GetMethod("WritePrivate", BindingFlags.NonPublic | BindingFlags.Instance);//無參私人非靜態方法
Console.WriteLine(method5.Name);
string s5 = method5.Invoke(temp1, null) as string;
Console.WriteLine("執行後:" + s5 + "\n");
MethodInfo method6 = itype.GetMethod("Show");//傳回型別為void的方法
Console.WriteLine(method6.Name);
object[]param3={"returnType is void"};
string s6 = method6.Invoke(temp1, param3) as string;
Console.WriteLine(s6);
//***********************************顯示所有屬性*********************************88//
Console.WriteLine("------------------------顯示所有屬性------------------------------");
PropertyInfo[] pros = itype.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo temp in pros)
{
Console.WriteLine(temp.Name);
}
//***********************************顯示特定屬性*********************************88//
Console.WriteLine("------------------------顯示特定屬性------------------------------");
PropertyInfo proName = itype.GetProperty("Name");
proName.SetValue(temp1, "testName",null);
Console.WriteLine(proName.GetValue(temp1, null));
//***********************************顯示建構函式*********************************88//
Console.WriteLine("------------------------顯示建構函式------------------------------");
ConstructorInfo[] cons = itype.GetConstructors();
foreach (ConstructorInfo t in cons)
{
Console.WriteLine(t.ToString());
}
//***********************************顯示特定建構函式形式*********************************88//
Console.WriteLine("------------------------顯示特定建構函式形式------------------------------");
ConstructorInfo con1= itype.GetConstructor(new Type[] { typeof(string), typeof(int) });
Console.WriteLine(con1);
ConstructorInfo con2 = itype.GetConstructor(new Type[] { });
Console.WriteLine(con2);
//**************************************委託的使用*********************************************//
Console.WriteLine("------------------------委託的使用------------------------------");
TestDelegate td = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), temp1, "WelcomeInfo");//非靜態方法
Console.WriteLine(td("使用的是帶有參數的非靜態方法"));
TestDelegate td2 = Delegate.CreateDelegate(typeof(TestDelegate), method1) as TestDelegate;//靜態方法
Console.WriteLine(td2("使用靜態方法"));
// TestDelegate td1 = new TestDelegate(SKY.ReflectDemo.ReflectTest.WriteStaticInfo);
// Console.WriteLine(td1("使用的是帶有參數的非靜態方法222")); 同上
運行結果如下:
有什麼不對,請大家批評指確。