今天來講解反射的應用:
一、反射是什么?
簡訴一下,反射就是.Net Framework 的一個幫助類庫,可以獲取並使用metadata(元數據清單);說的通俗易懂點,就是不用通過引用,仍然可以使用其他層的類。
二、讓我們建一個項目來開始操作吧!!!
1、建立一個控制台應用程序,並建立一個類庫,類庫里添加一個用戶類。

public class UsersInfo
{
public string Name { get; set; }
public bool Sex { get; set; }
public void CommonMethod()
{
Console.WriteLine("我是普通方法");
}
public void ParameterMethod(string name)
{
Console.WriteLine("我是帶參數方法,我叫"+name);
}
public void OverrideMethod(int age)
{
Console.WriteLine("我是重載方法,我今年"+age);
}
public void OverrideMethod(string name)
{
Console.WriteLine("我是重載方法,我叫" + name);
}
public void GenericityMethod<T>(T t)
{
Console.WriteLine("我是泛型方法方法,類型是"+typeof(T));
}
private void PrivateMethod()
{
Console.WriteLine("我是私有方法");
}
public static void StaticMethod()
{
Console.WriteLine("我是靜態方法");
}
}
2、利用反射獲取類庫,和類
- 第一步引用命名空間
- 第二步,動態加載類庫,寫要獲取類庫的絕對路徑
- 第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
}
}
}
}

3、利用反射獲取屬性,和屬性類型
- 遍歷類型的屬性集合
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
}
}
}
}
三、獲取方法(方法類型比較多,所以單獨做個模塊來寫)
- 創建一個符合類型的對象
- 指定要獲取的方法名稱
- 創建方法,第一個參數,對象,第二個參數,沒有則為空
1、獲取普通方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
Console.WriteLine("***********************普通方法*****************************");
object oUser = Activator.CreateInstance(type);//創建一個符合類型的對象
MethodInfo method = type.GetMethod("CommonMethod");//指定要獲取的方法名稱
method.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,沒有則為空
}
}
}
}

2、獲取帶參數的方法
- 指定要獲取的方法名稱
- 創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
Console.WriteLine("***********************普通方法*****************************");
object oUser = Activator.CreateInstance(type);//創建一個符合類型的對象
MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要獲取的方法名稱
commonMethod.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,沒有則為空
Console.WriteLine("***********************帶參數的方法*****************************");
MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要獲取的方法名稱
parameterMethod.Invoke(oUser, new object[] { "餐餐"});//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
}
}
}
}

3、重載方法
- 指定要獲取的方法名稱,和參數類型
- 創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
Console.WriteLine("***********************普通方法*****************************");
object oUser = Activator.CreateInstance(type);//創建一個符合類型的對象
MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要獲取的方法名稱
commonMethod.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,沒有則為空
Console.WriteLine("***********************帶參數的方法*****************************");
MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要獲取的方法名稱
parameterMethod.Invoke(oUser, new object[] { "餐餐"});//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法int參數*****************************");
MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要獲取的方法名稱,和參數類型
overrideMethodInt.Invoke(oUser, new object[] { 18 });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法string參數*****************************");
MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要獲取的方法名稱,和參數類型
overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
}
}
}
}

4、泛型方法
- 指定要獲取的方法名稱,和泛型參數類型
- 創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
Console.WriteLine("***********************普通方法*****************************");
object oUser = Activator.CreateInstance(type);//創建一個符合類型的對象
MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要獲取的方法名稱
commonMethod.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,沒有則為空
Console.WriteLine("***********************帶參數的方法*****************************");
MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要獲取的方法名稱
parameterMethod.Invoke(oUser, new object[] { "餐餐"});//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法int參數*****************************");
MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要獲取的方法名稱,和參數類型
overrideMethodInt.Invoke(oUser, new object[] { 18 });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法string參數*****************************");
MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要獲取的方法名稱,和參數類型
overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************泛型方法*****************************");
MethodInfo genericityMethod = type.GetMethod("GenericityMethod").MakeGenericMethod(new Type[] {typeof(int)});//指定要獲取的方法名稱,和泛型參數類型
genericityMethod.Invoke(oUser, new object[] { 123 });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
}
}
}
}

5、私有方法
- 指定要獲取的方法名稱,指明是父類的私有方法
- 創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//第一步引用命名空間
namespace Reflection
{
class Program
{
static void Main(string[] args)
{
{
Console.WriteLine("***********************獲取類*****************************");
//第二步,動態加載類庫,寫要獲取類庫的絕對路徑
Assembly assembly= Assembly.LoadFile(@"C:\Users\炸天張缺缺\Desktop\Reflection\Reflection.Model\bin\Debug\Reflection.Model.dll");
//第三步,動態獲取類型,寫類庫的名稱和類的名稱,不需要后綴
Type type = assembly.GetType("Reflection.Model.UsersInfo");
Console.WriteLine(type.Name);
Console.WriteLine("***********************獲取屬性*****************************");
//遍歷類型的屬性集合
foreach (var item in type.GetProperties())
{
Console.WriteLine(item.Name+" "+item.PropertyType);
}
Console.WriteLine("***********************普通方法*****************************");
object oUser = Activator.CreateInstance(type);//創建一個符合類型的對象
MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要獲取的方法名稱
commonMethod.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,沒有則為空
Console.WriteLine("***********************帶參數的方法*****************************");
MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要獲取的方法名稱
parameterMethod.Invoke(oUser, new object[] { "餐餐"});//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法int參數*****************************");
MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要獲取的方法名稱,和參數類型
overrideMethodInt.Invoke(oUser, new object[] { 18 });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************重載方法string參數*****************************");
MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要獲取的方法名稱,和參數類型
overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************泛型方法*****************************");
MethodInfo genericityMethod = type.GetMethod("GenericityMethod").MakeGenericMethod(new Type[] {typeof(int)});//指定要獲取的方法名稱,和泛型參數類型
genericityMethod.Invoke(oUser, new object[] { 123 });//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
Console.WriteLine("***********************泛型方法*****************************");
MethodInfo privateMethod = type.GetMethod("PrivateMethod",BindingFlags.Instance|BindingFlags.NonPublic);//指定要獲取的方法名稱,指明是父類的私有方法
privateMethod.Invoke(oUser,null);//創建方法,第一個參數,對象,第二個參數,是一個object對象數組,寫對應的參數類型
}
}
}
}

6、靜態方法
Console.WriteLine("***********************靜態方法*****************************");
MethodInfo staticMethod = type.GetMethod("StaticMethod");//指定要獲取的方法名稱
staticMethod.Invoke(null, null);//不需要實例化,所以第一個可以不寫,為空

四、小擴展,反射書寫ORM(請原諒我沒有注釋)
接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NineMonthExam.IDAL
{
public interface IEFHelpers<T> where T:class
{
bool Add(T t);
bool Remove(int id);
bool Edit(T t);
List<T> GetAll();
}
}
dbhelp類
using NineMonthExam.IDAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data.SqlClient;
using NineMonthExam.Model;
namespace NineMonthExam.DAL
{
public class DBHelpers<T> : IEFHelpers<T> where T : BaseModel
{
private static Type type;
private static string typeName;
private static string nameStr;
private static string noIdNameStr;
private static string sql = "";
private static StringBuilder addStr = new StringBuilder();
private static StringBuilder getStr = new StringBuilder();
private static StringBuilder removeStr = new StringBuilder();
private static StringBuilder modify = new StringBuilder();
private static StringBuilder modifyStr = new StringBuilder();
private static string conStr=ConfigurationManager.ConnectionStrings["conStr"].ConnectionString;
static DBHelpers()
{
type = typeof(T);
typeName = type.Name;
nameStr =string.Join(",", type.GetProperties().Select(m=>m.Name));
noIdNameStr = string.Join(",", type.GetProperties().Where(m=>!m.Name.Equals("Id")).Select(m => m.Name));
addStr.Append($@"insert into {typeName} ({noIdNameStr}) values ({string.Join(",", type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m =>$"@{m.Name}"))})");
getStr.Append($@"select {nameStr} from {typeName}");
removeStr.Append($@"delete from {typeName}");
modify.Append($@"update {typeName} set");
foreach (var item in type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m => m.Name))
{
modify.Append($@" {item}=@{item},");
}
string qian = modify.ToString();
qian = qian.Remove(qian.LastIndexOf(','));
modifyStr.Append(qian);
}
public bool Add(T t)
{
SqlParameter[] parameters = type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m => new SqlParameter($"@{m.Name}", m.GetValue(t) ?? DBNull.Value)).ToArray();
sql = addStr.ToString();
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand com = new SqlCommand(sql,conn);
com.Parameters.AddRange(parameters);
return com.ExecuteNonQuery() > 0;
}
}
public bool Edit(T t)
{
SqlParameter[] parameters = type.GetProperties().Select(m => new SqlParameter($"@{m.Name}", m.GetValue(t)??DBNull.Value)).ToArray();
string edit=$" where Id = @{type.GetProperty("Id").Name}";
sql = modifyStr.ToString()+ edit;
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand com = new SqlCommand(sql, conn);
com.Parameters.AddRange(parameters);
return com.ExecuteNonQuery() > 0;
}
}
private T GetT(SqlDataReader sdr)
{
T obj = Activator.CreateInstance(type) as T;
foreach (var item in type.GetProperties())
{
if (sdr[item.Name].GetType() != typeof(DBNull))
{
item.SetValue(obj, sdr[item.Name]);
}
else
{
item.SetValue(obj, null);
}
}
return obj;
}
public List<T> GetAll()
{
sql = getStr.ToString();
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand com = new SqlCommand(sql, conn);
SqlDataReader reader =com.ExecuteReader();
List<T> list = new List<T>();
while (reader.Read())
{
list.Add(GetT(reader));
}
return list;
}
}
public bool Remove(int id)
{
string del=$" where Id = {id}";
sql = removeStr.ToString()+del;
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand com = new SqlCommand(sql, conn);
return com.ExecuteNonQuery() > 0;
}
}
}
}
五、結束語:所有的成功都離不開努力,不要用不公平掩飾你不努力的樣子
所有的成功都離不開努力,不要用不公平掩飾你不努力的樣子
