一.需求:
交易返回的一大长串字符串:分项之间使用分割符‘|’分割。部分数据可能为空,如"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);