一.需求:
交易返回的一大長串字符串:分項之間使用分割符‘|’分割。部分數據可能為空,如"xx||xx",即每一數據項的位置是固定的。
如果數據為多條,記錄之間以‘$’分割。
例如:’xx|20200203|aaa1|$xx|20200104|aaa2|’.
二.分析 :
1. 多條記錄,首先就要進行分隔成一個數組,然后再對數組中的數據進行處理。
2.使用split方法對一條數據進行分隔為一個數據,那索引位置就對應着一個數據項。
3.在建立的實體的屬性上,添加一個定義的attribute來記錄這個數據項對應的索引,如LocationAttribute。
4.通過反射獲取對實體的所有屬性,遍歷屬性集合,獲取屬性上的索引,即可得到這個數據實際的值。
5.再通過反射創建實體的實例,給實體的屬性賦值。即可。
實現代碼:
namespace Cis.Hus.Service.Utils { /// <summary>/// </summary> public class StringUtils { /// <summary> /// 解析單個字符串為對象T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <returns></returns> public static T ParseOne<T>(string source) { string[] split = source.Split('|'); var accessor = new DynamicAccessor<T>(); T t = Activator.CreateInstance<T>(); var props = typeof(T).GetProperties(); foreach (var prop in props) { var p = prop.GetCustomAttributes(true).OfType<LocationAttribute>().FirstOrDefault(); if (p != null) { if (p.Column < split.Length) { var value = split[p.Column - 1]; var newValue = ChangeValueType(value, prop.PropertyType); accessor.SetValue(t, prop.Name, newValue); } } } return t; } /// <summary> /// /// </summary> /// <param name="value">要轉換的值</param> /// <param name="conversionType">要轉換成的類型</param> /// <returns></returns> private static object ChangeValueType(object value, Type conversionType) { if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if (value != null) { NullableConverter nullableConverter = new NullableConverter(conversionType); conversionType = nullableConverter.UnderlyingType; } else { return null; } } return Convert.ChangeType(value, conversionType); } /// <summary> /// 將字符串數組解析為對象數組 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <returns></returns> public static List<T> Parse<T>(string[] source) { List<T> result = new List<T>(); var type = typeof(T).GetType(); //反射訪問器 //TODO 測試一下,DynamicAccessor和 PropertyAccessor的性能差異 var accessor = new DynamicAccessor<T>(); for (int i = 0; i < source.Length; i++) { var one = ParseOne<T>(source[i]); result.Add(one); } return result; } /// <summary> /// 將字符串解析為對象數組 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <returns></returns> public static List<T> Parse<T>(string source) { //如果業務數據為多條記錄,記錄之間以‘$’分割 if (source.Contains("$")) { string[] items = source.Split('$'); return Parse<T>(items); } var obj = ParseOne<T>(source); return new List<T> { obj }; } } }
/// <summary> /// 插入定位attribute /// </summary> [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)] public class LocationAttribute : Attribute { #region Fields /// <summary> /// 列索引 /// </summary> public int Column { get; set; } #endregion }
調用:
List<User> data = StringUtils.Parse<User>(data);