資料通常會使用ORM Mapper到 Model上,再將結果View Model將資料直接傳到View上作使用,當變更行為確認時會將View Model傳回Controller寫入資料到DB。
但是View Model也許是多個Entity Model所組成因此在沒有使用任何Mapper工具底下就必須寫類似下方的程式碼。
User User = new User();
Mail Mail = new Mail();
Address Address = new Address();
User.UserId = UserV.UserId;
User.UserName = UserV.UserName;
User.Sex = UserV.Sex;
Mail.EMail = UserV.EMail;
Address.Address1 = UserV.Address1;
Address.Address2 = UserV.Address2;
Address.Address3 = UserV.Address3;
為了解決這個問題因此網路上有一些可以做到Mapper的工具AutoMapper、TinyMapper、ExpressMapper等等...,也有一些評比當然使用上是依照專案需求。
本次實作的概念:將UserV Mapper到User、Tel、Address、Mail簡易做法,Class Name作為Table Name,Attributes Name作為Column Name、透過這樣定義完成 Mapper。
使用方法:
屬性定義[CustomerAttributes.RefColumn("Class Name,Attributes Name;....")]
[CustomerAttributes.RefColumn("User,UserId;Address,UserId;Mail,UserId;Tel,UserId")]
public string UserId { get; set; }
使用範例:
private void button1_Click(object sender, EventArgs e)
{
UserV UserV = new UserV();
UserV.UserId = "E001";
UserV.UserName = "Name";
UserV.Sex = "M";
UserV.EMail = "Test@Test.com.tw";
UserV.Address1 = "台北市";
User objUser = UserV.ToNewObject<User>(new User(), "User");
Mail objMail = UserV.ToNewObject<Mail>(new Mail(), "Mail");
}
Model:
User、Tel、Address、Mail
public class User
{
public string UserId { get; set; }
public string UserName { get; set; }
public string Sex { get; set; }
}
public class Tel
{
public string UserId { get; set; }
public string TelAreacode { get; set; }
public string TelNo { get; set; }
public string TelExt { get; set; }
public string TelType { get; set; }
}
public class Address
{
public string UserId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
}
public class Mail
{
public string UserId { get; set; }
public string EMail { get; set; }
}
public class UserV
{
[CustomerAttributes.RefColumn("User,UserId;Address,UserId;Mail,UserId;Tel,UserId")]
public string UserId { get; set; }
[CustomerAttributes.RefColumn("User,UserName")]
public string UserName { get; set; }
[CustomerAttributes.RefColumn("User,Sex")]
public string Sex { get; set; }
[CustomerAttributes.RefColumn("Address,Address1")]
public string Address1 { get; set; }
[CustomerAttributes.RefColumn("Address,Address2")]
public string Address2 { get; set; }
[CustomerAttributes.RefColumn("Address,Address3")]
public string Address3 { get; set; }
[CustomerAttributes.RefColumn("Mail,EMail")]
public string EMail { get; set; }
[CustomerAttributes.RefColumn("Tel,TelAreacode")]
public string TelAreacode { get; set; }
[CustomerAttributes.RefColumn("Tel,TelNo")]
public string TelNo { get; set; }
[CustomerAttributes.RefColumn("Tel,TelExt")]
public string TelExt { get; set; }
[CustomerAttributes.RefColumn("Tel,TelType")]
public string TelType { get; set; }
}
結果:
程式碼:
新增CustomerAttributes.cs
定義Mapper需要屬性
[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class RefColumn : Attribute
{
private string _obj;
/// <summary>
/// 設定關聯欄位(支援多筆,使用分號相隔,每筆資料[Table,Column];例:CNFLWF,CONT_NO_OR_MA_STOP_NO;CNCOVM,CONT_NO)
/// </summary>
/// <param name="obj" />關聯欄位字串格式
public RefColumn(string obj)
{
this._obj = obj;
}
public class Receive
{
public IList<refcolumnobj> RefColumn { get; set; }
}
public class RefColumnObj
{
/// <summary>
/// Table Name
/// </summary>
public string Table { get; set; }
/// <summary>
/// Column Name
/// </summary>
public string Column { get; set; }
}
}
實作CustomerAttributes.RefColumn.GetValue
將傳入的定義解析(";" 幾組)("," [0]Class Name、[1]Attributes Name),找出該對應的Class屬性。
public IList GetValue
{
get
{
IList result = new List();
string[] cols = _obj.Split(';');
foreach (var item in cols)
{
string[] paras = item.Split(',');
result.Add(new RefColumnObj() { Table = paras[0].Trim(), Column = paras[1].Trim() });
}
return result;
}
}
實作CustomerAttributes.GetRefColumn
取得RefColumn的資料。
/// <summary>
/// 取得RefColumn的資料
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="property"></param>
/// <returns></returns>
public static IList<RefColumn.RefColumnObj> GetRefColumn(System.Reflection.PropertyInfo property)
{
var attrs = (RefColumn[])property.GetCustomAttributes(typeof(RefColumn), false);
//IList<RefColumn.RefColumnObj> result = new List<RefColumn.RefColumnObj>();
//foreach (var item in attrs)
//{
//result = item.GetValue;
//}
IList result = attrs.Select(x => x.GetValue).ToList()[0];
return result;
}
實作ToNewObject
將傳入的Class 轉換為指定輸出的Class。
/// <summary>
/// 複製成new object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="target"></param>
/// <param name="tableName"></param>
/// <returns></returns>
public static T ToNewObject(this object source, T target, string tableName)
{
if (source != null)
{
foreach (PropertyInfo objItem in source.GetType().GetProperties())
{
var attr = CustomerAttributes.GetRefColumn(objItem);
foreach (var item in attr)
{
if (item.Table.Equals(tableName))
{
PropertyInfo property = target.GetType().GetProperty(item.Column);
if (property != null && objItem.GetValue(source, null) != null && property.PropertyType == objItem.PropertyType)
{
//找出是否有對應欄位,有則設值
property.SetValue(target, objItem.GetValue(source, null), null);
}
}
}
}
}
return target;
}
參考:專案經驗



沒有留言:
張貼留言