反射讓代碼在運行時檢查、操作類型。典型應用:插件系統、ORM 映射、配置驅動、序列化框架。
public class ObjectLoader
{
private readonly Assembly _assembly;
public ObjectLoader(string assemblyName)
=> _assembly = Assembly.Load(assemblyName);
// 1. 創建實例 (需含命名空間)
public object CreateInstance(string typeName)
=> _assembly.CreateInstance($"{_assembly.GetName().Name}.{typeName}");
// 2. 獲取所有公共屬性
public PropertyInfo[] GetProperties(object obj)
=> obj.GetType().GetProperties();
// 3. 設置屬性值
public void SetProperty(object obj, string propName, object value)
{
var prop = obj.GetType().GetProperty(propName);
prop?.SetValue(obj, value, null);
}
// 4. 讀取屬性值
public object GetProperty(object obj, string propName)
{
var prop = obj.GetType().GetProperty(propName);
return prop?.GetValue(obj, null);
}
// 5. 執行無參方法
public void InvokeMethod(object obj, string methodName)
{
var method = obj.GetType().GetMethod(methodName);
method?.Invoke(obj, null);
}
}
namespace Model
{
public class UserInfo
{
public int UserId { get; set; }
public string UserName { get; set; }
public void Show() => Console.WriteLine($"UserId:{UserId}, UserName:{UserName}");
}
}
var loader = new ObjectLoader("Model");
object user = loader.CreateInstance("UserInfo");
Console.WriteLine($"實例: {user.GetType().FullName}");
foreach (var p in loader.GetProperties(user))
Console.WriteLine($"{p.PropertyType.Name} {p.Name}");
loader.SetProperty(user, "UserId", 1);
loader.SetProperty(user, "UserName", "admin");
Console.WriteLine($"UserId: {loader.GetProperty(user, "UserId")}");
Console.WriteLine($"UserName: {loader.GetProperty(user, "UserName")}");
loader.InvokeMethod(user, "Show");
// 輸出: UserId:1, UserName:admin
`Type.InvokeMember` 可綁定標志一次完成創建、調用、屬性/字段讀寫。
Type type = typeof(Love);
object obj = type.InvokeMember(null,
BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, null, null);
// 調用方法
type.InvokeMember("Display", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null, obj, new object[] { "hello" });
// 設置屬性
type.InvokeMember("Name", BindingFlags.SetProperty, null, obj, new object[] { "abc" });
// 讀取屬性
string name = (string)type.InvokeMember("Name", BindingFlags.GetProperty, null, obj, null);
// 設置字段
type.InvokeMember("field1", BindingFlags.SetField, null, obj, new object[] { 444 });
// 讀取字段
int val = (int)type.InvokeMember("field1", BindingFlags.GetField, null, obj, null);
public static class DataTableMapper
{
public static List<T> ToList<T>(this DataTable table) where T : new()
{
var loader = new ObjectLoader(typeof(T).Assembly.GetName().Name);
var list = new List<T>();
var props = typeof(T).GetProperties()
.Where(p => p.CanWrite)
.ToDictionary(p => p.Name, p => p);
foreach (DataRow row in table.Rows)
{
T entity = new T();
foreach (DataColumn col in table.Columns)
{
if (props.TryGetValue(col.ColumnName, out var prop)
&& row[col] != DBNull.Value)
{
// 類型轉換處理
object value = row[col];
if (prop.PropertyType != value.GetType())
value = Convert.ChangeType(value, prop.PropertyType);
prop.SetValue(entity, value);
}
}
list.Add(entity);
}
return list;
}
}
// 使用
var users = dataTable.ToList<UserInfo>();
| 標志 | 含義 |
|---|---|
| Public / NonPublic | 公共 / 非公共成員 |
| Instance / Static | 實例 / 靜態成員 |
| DeclaredOnly | 僅當前類型聲明,不含繼承 |
| CreateInstance | 調用構造函數 |
| InvokeMethod | 調用方法 |
| GetProperty / SetProperty | 讀/寫屬性 |
| GetField / SetField | 讀/寫字段 |
PropertyInfo[]、MethodInfo 避免重複反射Delegate.CreateDelegate 轉為強類型委托Expression.Compile() 生成委托GetType()/GetProperty()反射是框架級開發的基石,掌握動態創建、屬性映射、方法調用三板斧,即可構建屬於自己的微型 ORM 或插件容器。