反射+自定义特性保存数据至本地

  • A+
所属分类:.NET技术
摘要

最近在项目过程中遇到了保存数据的需求,对实体类的部分数据进行保存,打算采用反射+自定义特性来实现数据保存,利于扩展
1. 采用反射实现能够灵活获取要保存的数据,由于只需要保存实体类(Model)的部分数据,因此采用自定义特性标记需要保存的数据,同时数据要求以.csv格式保存,添加自定义特性有利于对表头进行描述
2. 实现自定义特性

最近在项目过程中遇到了保存数据的需求,对实体类的部分数据进行保存,打算采用反射+自定义特性来实现数据保存,利于扩展
1. 采用反射实现能够灵活获取要保存的数据,由于只需要保存实体类(Model)的部分数据,因此采用自定义特性标记需要保存的数据,同时数据要求以.csv格式保存,添加自定义特性有利于对表头进行描述
2. 实现自定义特性

    public class ResultAttribute : Attribute     {         private bool _IsSave;         /// <summary>         /// 是否保存         /// </summary>         public bool IsSave         {             get { return _IsSave; }             set { _IsSave = value; }         }          private string _SaveName;         /// <summary>         /// .csv文件第一行的名称         /// </summary>         public string SaveName         {             get { return _SaveName; }             set { _SaveName = value; }         }     } 
  1. Model类添加自定义标签
    添加自定义标签后,反射过程中就能识别要保存的属性和.csv头名称
 public class TestResultModel:ViewModelBase     {          private int _TestNumber;         /// <summary>         /// 序号         /// </summary>         [EquationResult(SaveName = "序号", IsSave = true)]         public int TestNumber         {             get { return _TestNumber; }             set { _TestNumber = value; RaisePropertyChanged(); }         }          private string _TestResult;         /// <summary>         /// 测试结果         /// </summary>         [EquationResult(SaveName = "测试结果", IsSave = true)]         public string TestResult         {             get { return _TestResult; }             set { _TestResult = value; RaisePropertyChanged(); }         }          private DateTime _TestTime;         /// <summary>         /// 测试时间         /// </summary>         [EquationResult(SaveName = "测试时间", IsSave = true)]         public DateTime TestTime         {             get { return _TestTime; }             set { _TestTime = value; RaisePropertyChanged(); }         } 						         private string _MeterSn;         /// <summary>         /// 仪器SN号         /// </summary>         public string MeterSn         {             get { return _MeterSn; }             set { _MeterSn = value; RaisePropertyChanged(); }         }    }	 
  1. 使用反射进行数据保存
 /// <summary>         /// 获得要保存的数据         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="tClass"></param>         /// <param name="IsHead">是不是第一行的表头</param>         /// <returns></returns>         private string GetSaveStr<T>(T tClass, bool IsHead = false) where T : class         {             StringBuilder sb = new StringBuilder();             //msdn:GetProperties方法不按特定顺序(如字母顺序或声明顺序)返回属性。 你的代码不能依赖属性的返回顺序,因为该顺序会有所不同。              PropertyInfo[] infoarr = tClass.GetType().GetProperties();                       foreach (var property in infoarr)             {                 if (property.GetCustomAttribute(typeof(EquationResultAttribute), false) is EquationResultAttribute bute)                 {                     if (bute.IsSave && IsHead)                     {                         sb.Append(bute.SaveName + ",");                     }                     else if (bute.IsSave && !IsHead)                     {                         sb.Append(property.GetValue(tClass).ToString() + ",");                     }                     else                     {                         ;//无代码                     }                 }             }             return sb.ToString();         }            /// <summary>         /// 保存测试信息         /// </summary>         /// <param name="listModel"></param>         public void SaveTestDataToCsv(List<TestDataModel> listModel)         {             using (FileStream fs = new FileStream(CsvSavePath, FileMode.OpenOrCreate, FileAccess.Write))             {                 using (StreamWriter sw = new StreamWriter(fs,Encoding.Default))                 {                     sw.BaseStream.Seek(0, SeekOrigin.Begin);            //设置流的起始位置为开始                     string data = GetSaveStr(listModel[0], true);       //写入第一行                     sw.WriteLine(data);  //写入数据流                     sw.Flush();                     for (int i = 0; i < listModel.Count; i++)                     {                         sw.BaseStream.Seek(0, SeekOrigin.End);                         data = GetSaveStr(listModel[i]);                         sw.WriteLine(data);  //写入数据流                         sw.Flush();                     }                 }             }         } 
  1. 使用反射获取属性列表时,列表的顺序可能会不一致,可以在自定义特性中加入排序特性,对每个属性设置排序值,反射获取属性列表后同时获取排序特性,根据排序特性对属性列表进行排序保证每次属性列表的顺序一致