資料通常會使用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 IListGetValue { 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; //} IListresult = 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; }
專案經驗
沒有留言:
張貼留言