目錄:
一. 反射的主要特性
1.反射中一個非常重要的類型就是 Type
1)當沒有對象的時候使用這種方式來獲取某個類型的Type
2)當已經獲得對象後通過對象的GetType()方法來獲取指定對象的類型的Type對象
2.獲取Person類中的所有的方法
3.獲取某個類型的所有屬性
4.獲取類中的所有字段,私有字段無法獲取
5.獲取所有成員,不包含私有成員
二. 反射動態加載程序集
1.動態加載一個程序集
2.獲取剛剛加載的程序集中的所有的類型
1)GetTypes()獲取了所有的類型
2)只獲取那些public的類型
3.獲取程序集中某個類的Type
4.動態調用類的方法
1)調用無參數無返回值的方法
2) 調用帶參數,帶返回值的方法
1> 調用不帶重載的方法
2>調用帶重載的方法
5. 通過反射獲取類的屬性,並賦值
1)獲取Name屬性
2)為屬性賦值
3) 獲取屬性值
4)獲取方法並調用
6.手動查找類型的構造函數,並且調用該構造函數來創建類型的對象
三. 其他的反射中的一些方法
1. bool IsAssignableFrom(Type c) 判斷當前的類型的變量是不是可以接受c類型變量的賦值
2. bool IsInstanceOfType(object o):判斷對象o是否是當前類的實例(當前類可以是o的類、父類、接口)
3. bool IsSubclassOf(Type c):判斷當前類是否是類c的子類
4. IsAbstract 判斷是否為抽象的,含接口
————————————————————————————————————————————————————————————————————————————
反射是什麼?
反射:通過動態獲取程序集,並獲取其中的類型元數據,然後訪問該類型的過程。
一. 反射的主要特性
在介紹反射的主要特性之前我們先建一個Person類(下面都是對Person類進行操作)
class Person { public int _height; public string Name { get; set; } public int Age { get; set; } public string Email { get; set; } public void Say() { Console.WriteLine("Hello everyone!"); } public void SayMorning() { Console.WriteLine("Good morning everybody!"); } //私有的 void Do() { Console.WriteLine("Just do it!"); } } View Code1.反射中一個非常重要的類型就是 Type
獲取Person類型的Type對象(Type對象中就是存放了一些關於某個類型的所有信息的內容。[某個類型的Type對象就是該類型“類型元數據”])
獲取Type對象有兩種方法:
1)當沒有對象的時候使用這種方式來獲取某個類型的Type
Type type = typeof(Person);
2)當已經獲得對象後通過對象的GetType()方法來獲取指定對象的類型的Type對象
Person p = new Person();
Type personType = p.GetType();
2.獲取Person類中的所有的方法
(通過Type對象的GetMethods()可以獲取指定類型的所有的方法其中包括編譯器自動生成的方法以及從父類中繼承來的方法,但是不包含private方法)
MethodInfo[] methods = personType.GetMethods();
for (int i = 0; i < methods.Length; i++)
{
Console.WriteLine(methods[i].Name);
}
3.獲取某個類型的所有屬性
PropertyInfo[] properties = personType.GetProperties();
for (int i = 0; i < properties.Length; i++)
{
Console.WriteLine(properties[i].Name);
}
Console.ReadKey();
4.獲取類中的所有字段,私有字段無法獲取
FieldInfo[] fields = personType.GetFields();
for (int i = 0; i < fields.Length; i++)
{
Console.WriteLine(fields[i].Name);
}
Console.ReadKey();
5.獲取所有成員,不包含私有成員
MemberInfo[] members = personType.GetMembers();
for (int i = 0; i < members.Length; i++)
{
Console.WriteLine(members[i].Name);
}
Console.ReadKey();
二. 反射動態加載程序集
在接收發射動態加載程序集,先把程序級的代碼貼出來(下面都是對程序集TestDll.dll進行操作)
namespace TestDll { public class Class1 { } class MyClass { public void English() { Console.WriteLine("Hi,English"); } } public abstract class MyAbstractClass { } public static class MyStaticClass { } public class Person { public Person() { } public Person(string name, int age, string email) { this.Name = name; this.Age = age; this.Email = email; } public string Name { get; set; } public int Age { get; set; } public string Email { get; set; } public void GetNameValue() { Console.WriteLine(this.Name + "--" + this.Age + "--" + this.Email); } public void English() { Console.WriteLine("Hi,English"); } public void China() { Console.WriteLine("你好,中國"); } public int Add(int n1, int n2) { return n1 + n2; } public int Add(int n1, int n2, int n3) { return n1 + n2 + n3; } } public class Student : Person, IFlyable { public string StudentNo { get; set; } #region IFlyable 成員 public void Fly() { Console.WriteLine("I can Fly!"); } #endregion } class Teacher : Person { } public delegate void MyDelegate(); delegate void MyDelegate1(); public enum GoodMan { 高, 富, 帥 } public interface IFlyable { void Fly(); } } View Code1.動態加載一個程序集
Assembly assembly = Assembly.LoadFile(@"D:\TestDll\bin\Debug\TestDll.dll");
注意:這個地址是程序及所在的絕對地址
2.獲取剛剛加載的程序集中的所有的類型
assembly.GetType() 等價於 typeof(Assembly)
1)GetTypes()獲取了所有的類型
Type[] types = assembly.GetTypes();
2)只獲取那些public的類型
Type[] types = assembly.GetExportedTypes();
for (int i = 0; i < types.Length; i++)
{
Console.WriteLine(types[i].Name);
}
3.獲取程序集中某個類的Type
如:只獲取Person類的Type
GetType()方法有重載,選擇第二個重載,參數表示是要獲取的類型的“完全限定名稱”,即:命名空間.類名
這裡拿到了Type,其實就等價於typeof(Person)或者是:p.GetType();
Type personType = assembly.GetType("_02TestDll.Person");
獲取所有的方法:personType.GetMethods();
4.動態調用類的方法
(借用上面獲取的Person類的方法)
獲取某個特定的方法(根據方法名):personType.GetMethod();
1)調用無參數無返回值的方法
MethodInfo method = personType.GetMethod("SayHi");
Console.WriteLine(method.Name);
//通過反射來創建一個Person類型的對象{其實就是通過Person的Type來創建一個Person對象}
object objPerson = Activator.CreateInstance(personType);
//調用這個方法
method.Invoke(objPerson, null);
2) 調用帶參數,帶返回值的方法
1> 調用不帶重載的方法
//找到對應的方法
MethodInfo method = personType.GetMethod("Add");
object obj = Activator.CreateInstance(personType);
//調用
object result = method.Invoke(obj, new object[] { 102, 203 });
Console.WriteLine("調用Add方法的返回值結果是:{0}", result);
#endregion
2>調用帶重載的方法
//找到對應的方法
MethodInfo method = personType.GetMethod("Add", new Type[] { typeof(int), typeof(int), typeof(int) });
object obj = Activator.CreateInstance(personType);
//調用
int r = (int)method.Invoke(obj, new object[] { 1, 2, 3 });
Console.WriteLine(r);
5. 通過反射獲取類的屬性,並賦值
(借用上面獲取的Person類的方法)
1)獲取Name屬性
PropertyInfo property = personType.GetProperty("Name");
object obj = Activator.CreateInstance(personType);
2)為屬性賦值
property.SetValue(obj, "張三", null);
3) 獲取屬性值
string name = property.GetValue(obj, null).ToString();
Console.WriteLine(name);
4)獲取方法並調用
MethodInfo method = personType.GetMethod("GetNameValue");
method.Invoke(obj, null);
Console.ReadKey();
6.手動查找類型的構造函數,並且調用該構造函數來創建類型的對象
查找到了對應的構造函數,但是還沒有調用
ConstructorInfo ctor = personType.GetConstructor(new Type[] { typeof(string), typeof(int), typeof(string) });
開始調用構造函數
object obj = ctor.Invoke(new object[] { "hpp", 16, "[email protected]" });
Console.WriteLine(obj.ToString());
MethodInfo method = personType.GetMethod("GetNameValue");
method.Invoke(obj, null);
Console.ReadKey();
三. 其他的反射中的一些方法
//動態加載一個程序集
Assembly assembly = Assembly.LoadFile(@"D:\TestDll\bin\Debug\TestDll.dll");
//獲取類的Type
Type typePerson = assembly.GetType("TestDll.Person");
Type typeStudent = assembly.GetType("TestDll.Student");
Type typeIFlyable = assembly.GetType("TestDll.IFlyable");
1. bool IsAssignableFrom(Type c) 判斷當前的類型的變量是不是可以接受c類型變量的賦值
//表示可以將Student類型賦值給Person類型,因為Student類型繼承自Person類
bool b = typePerson.IsAssignableFrom(typeStudent); //true
//表示可以將Student類型賦值給IFlyable類型,因為Student類型繼承自IFlyable接口
bool b = typeIFlyable.IsAssignableFrom(typeStudent);//true
//表示不可以將Person類型賦值給IFlyable類型,因為Person類型沒有繼承IFlyable接口
bool b = typeIFlyable.IsAssignableFrom(typePerson);//false
2. bool IsInstanceOfType(object o):判斷對象o是否是當前類的實例(當前類可以是o的類、父類、接口)
//Person
object objPerson = Activator.CreateInstance(typePerson);
//Student
object objStudent = Activator.CreateInstance(typeStudent);
//當前類就是Person類
bool b = typePerson.IsInstanceOfType(objPerson);//true
//Suntent類是Person類的子類
bool b = typePerson.IsInstanceOfType(objStudent);//true
//person類不是Student的子類
bool b = typeStudent.IsInstanceOfType(objPerson);//false
3. bool IsSubclassOf(Type c):判斷當前類是否是類c的子類
//Person
object objPerson = Activator.CreateInstance(typePerson);
//Student
object objStudent = Activator.CreateInstance(typeStudent);
//Suntent類是Person類的子類
bool b = typeStudent.IsSubclassOf(typePerson);//true
//person類不是Student的子類
bool b = typePerson.IsSubclassOf(typeStudent);//false
//這個返回是false,只驗證類與類之間的父子類關系,接口不包含。
bool b = typeStudent.IsSubclassOf(typeIFlyable);
4. IsAbstract 判斷是否為抽象的,含接口
Type typeMyAbsClass = assembly.GetType("TestDll.MyAbstractClass");
Type typeMyStaticClass = assembly.GetType("TestDll.MyStaticClass");
Console.WriteLine(typePerson.IsAbstract);//false;
Console.WriteLine(typeStudent.IsAbstract);//false
Console.WriteLine(typeIFlyable.IsAbstract);//true
Console.WriteLine(typeMyAbsClass.IsAbstract);//true
Console.WriteLine(typeMyStaticClass.IsAbstract); //true
Console.ReadKey();
以上就是反射的一些介紹以及一些放大的基本用法······