延續昨天的使用 AutoMapper 的主題。如果你的專案不能使用 AutoMapper 的話,那就只能使用反射(Reflection)來實作了。今天我們用反射(Reflection)來把 UserViewModel
的資料倒進 Model
裡面。
以下程式,我們先進行用反射的方式取得物件全部屬性(Property)的值。
var userViewModel = new UserViewModel(){
Id=1,
Email="aaa@test.com",
Name="長庚",
Phone="123456789"
};
// 先取出 UserViewModel 型別中所有 Property 資訊 (PropertyInfo型別)
var propertyInfos = typeof(UserViewModel).GetProperties();
// 迴圈對 UserViewModel 型別的各個 PropertyInfo 處裡
foreach (var propertyInfo in propertyInfos)
{
// 把 userViewModel 餵給 propertyInfo,來取得 userViewModel 該 Property 的值
var value = propertyInfo.GetValue(userViewModel);
Console.WriteLine($"{propertyInfo.Name}:{value}");
}
Id:1
Email:aaa@test.com
Name:長庚
Phone:123456789
再下一步就是把值餵給目標物件的同名屬性(Property)。我們稍微改一下程式。
上面不變先省略 ...
// 宣告要被賦值的目標物件
var user = new User();
// 迴圈對來源型別的各個 PropertyInfo 處裡
foreach (var propertyInfo in propertyInfos)
{
// 把 userViewModel 餵給 propertyInfo,來取得 userViewModel 該 Property 的值
var value = propertyInfo.GetValue(userViewModel);
// 取得目標型別 (User) 的 propertyInfo
var userPropertyInfo = typeof(User).GetProperty(propertyInfo.Name);
// 使用 User 的 propertyInfo 對目標物件 (user) 的該 Property 賦值
userPropertyInfo.SetValue(user, value);
}
上面的寫法是固定型別的,我們用泛型來稍微改造一下,就可以一個方法能讓全部型別可以 Map 為其他型別(當然要欄位名稱同樣)。
public static class MyMapper
{
public static TTarget Map<TOrigin, TTarget>(TOrigin origin) where TTarget : new()
{
if (origin == null)
{
throw new ArgumentNullException();
}
var target = new TTarget();
// 先取出來源型別中所有 Property 資訊 (PropertyInfo型別)
var propertyInfos = typeof(TOrigin).GetProperties();
// 迴圈對型別的各個 PropertyInfo 各自處裡
foreach (var propertyInfo in propertyInfos)
{
// 把物件餵給 property,來取得此物件此 Property 的值
var value = propertyInfo.GetValue(origin);
// 取得目標型別的 Property
var targetProperty = typeof(TTarget).GetProperty(propertyInfo.Name);
// 使用目標型別的 propertyInfo 對目標物件的該 Property 賦值
targetProperty?.SetValue(target, value);
}
return target;
}
}
這樣我們只要一行就能把 ViewModel 的資料,倒進 Model 裡!!!