反射+自定義特性保存數據至本地

最近在項目過程當中遇到了保存數據的需求,對實體類的部分數據進行保存,打算採用反射+自定義特性來實現數據保存,利於擴展
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. 使用反射獲取屬性列表時,列表的順序可能會不一致,能夠在自定義特性中加入排序特性,對每一個屬性設置排序值,反射獲取屬性列表後同時獲取排序特性,根據排序特性對屬性列表進行排序保證每次屬性列表的順序一致
相關文章
相關標籤/搜索