// public InfoPlusUser workflowOperator { get; set; } // public DateTime ? operateTime { get; set; } /// <summary> /// Convert InfoPlusEvent FormData to strongly-typed entity /// </summary> /// <typeparam name="T"></typeparam> /// <param name="e"></param> /// <returns></returns> public static T Convert <T>(InfoPlusEvent e) { if (null == e) { return(default(T)); } // 1. FormData T o = InfoPlusEntity.Convert <T>(e.FormData, e.Fields, false); // 2.InfoPlusEntity Related InfoPlusEntity en = o as InfoPlusEntity; if (null != en && null != e.Step) { // RenderUri try { en.RenderUri = e.Step.RenderUri; } catch (Exception) { } // Instance if (null != e.Step.Instance) { en.InstanceId = e.Step.Instance.InstanceId; en.BusinessId = e.Step.Instance.BusinessId; if (null != e.Step.Instance.Creator) { en.InstanceOwner = e.Step.Instance.Creator.Account; } } } return(o); }
/// <summary> /// Convert data recursively, from weakly-typed(transfer presentation map) to strongly-typed entity. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"></param> /// <param name="fields"></param> /// <param name="withIndex">true if data are from other sources including api. externData with set all EntityIndex to -1</param> /// <returns></returns> public static T Convert <T>(IDictionary <string, object> data, IList <FormField> fields, bool external) { if (null == data) { return(default(T)); } Type type = typeof(T); object x = default(T); return((T)InfoPlusEntity.Convert(data, fields, ref x, 0, type, 0, string.Empty, external)); }
/// <summary> /// Convert strong-typed entity to map presentation for transfer /// </summary> /// <typeparam name="T"></typeparam> /// <param name="o"></param> /// <param name="fields"></param> /// <returns></returns> public static IDictionary <string, object> Convert <T>(T o, IList <FormField> fields) { IDictionary <string, object> data = null; if (null == fields) { return(data); } int min = fields.Select(f => InfoPlusEntity.CalculateGroupDepth(f.GroupName)).Min(); var g0 = fields.Where(f => InfoPlusEntity.CalculateGroupDepth(f.GroupName) == min) .Select(f => f.GroupName).First(); InfoPlusEntity.Convert(o, fields, g0, null, 0, ref data); return(data); }
static void Convert(object o, IList <FormField> fields, string groupPath, string dataPath, int depth, ref IDictionary <string, object> data) { if (null == o) { return; } if (null == dataPath) { dataPath = string.Empty; } Type type = o.GetType(); if (null == data) { data = new Dictionary <string, object>(); } // current level, read property directly. // should always be equal, Only, except the initial call. string[] groups = groupPath.Split(new string[] { "//" }, StringSplitOptions.RemoveEmptyEntries); if (groups.Length > depth + 1) { string gn = InfoPlusEntity.ParseGroupName(groups[depth + 1]); PropertyInfo property = type.GetProperty(gn); if (null == property) { return; } object deeps = property.GetValue(o, null); Array arr = InfoPlusEntity.ObjectToArray(deeps); if (null == arr) { return; } for (int n = 0; n < arr.Length; n++) { object deep = arr.GetValue(n); InfoPlusEntity.Convert(deep, fields, groupPath, dataPath + "/" + n, depth + 1, ref data); } } else { var currentFields = fields.Where(f => f.GroupName == groupPath); foreach (FormField field in currentFields) { string propertyName, fieldName; InfoPlusEntity.ParsePropertyName(field.Name, out propertyName, out fieldName); PropertyInfo property = type.GetProperty(propertyName); if (null == property) { continue; } object val = property.GetValue(o, null); InfoPlusEntity.FormDataAssign(fieldName, val, data, dataPath); } var deepers = from f in fields where InfoPlusEntity.CalculateGroupDepth(f.GroupName) > depth && f.GroupName.Contains(groupPath) select f; if (deepers.Count() > 0) { int min = deepers.Select(f => InfoPlusEntity.CalculateGroupDepth(f.GroupName)).Min(); var groupNames = deepers.Where(f => InfoPlusEntity.CalculateGroupDepth(f.GroupName) == min) .Select(f => f.GroupName).Distinct().ToList(); foreach (string groupName in groupNames) { string[] gns = groupName.Split(new string[] { "//" }, StringSplitOptions.RemoveEmptyEntries); if (depth < gns.Length - 1) { string gn = InfoPlusEntity.ParseGroupName(gns[depth + 1]); PropertyInfo property = type.GetProperty(gn); if (null == property) { continue; } object deeps = property.GetValue(o, null); Array arr = InfoPlusEntity.ObjectToArray(deeps); if (null == arr) { continue; } // assign inner field to array in case of empty. if (0 == arr.Length) { var groupFields = deepers.Where(f => f.GroupName == groupName); foreach (var field in groupFields) { InfoPlusEntity.FormDataAssign(field.Name, new Array[0], data, dataPath); } } for (int n = 0; n < arr.Length; n++) { object deep = arr.GetValue(n); InfoPlusEntity.Convert(deep, fields, groupName, dataPath + "/" + n, depth + 1, ref data); } } } } } }
static object Convert(IDictionary <string, object> data, IList <FormField> fields, ref object o, int depth, Type type, int index, string path, bool external) { depth++; // not created before? create it. if (null == o) { o = Activator.CreateInstance(type); var propIndex = type.GetProperty("EntityIndex"); if (null != propIndex && propIndex.PropertyType == typeof(int)) { propIndex.SetValue(o, (external ? -1 : index), null); } var propPath = type.GetProperty("EntityPath"); if (null != propPath && propPath.PropertyType == typeof(string)) { propPath.SetValue(o, path, null); } /* * var fieldIndex = type.GetField("EntityIndex"); * if (null != fieldIndex && fieldIndex.FieldType == typeof (int)) * { * fieldIndex.SetValue(o, index); * } */ } if (null == o) { throw new Exception("Activator.CreateInstance<T> failed. where T is " + type.FullName); } foreach (string key in data.Keys) { string property; string fieldName; bool isName = InfoPlusEntity.ParsePropertyName(key, out property, out fieldName); object val = data[key]; Array arr = InfoPlusEntity.ObjectToArray(val); // Primitive. if (null == arr) { InfoPlusEntity.SetValue(o, property, val); } else { // If key is "_Name", find the origal fieldName and resize the Array Array a0 = null; if (isName) { if (false == data.ContainsKey(fieldName)) { arr = new object[0]; } else { object v0 = data[fieldName]; a0 = InfoPlusEntity.ObjectToArray(v0); if (null == a0 || 0 == a0.Length) { arr = new object[0]; } else if (a0.Length < arr.Length) { arr = arr.Cast <object>().Take(a0.Length).ToArray(); } } } string groupName = null; if (null != fields) { var field = (from f in fields where f.Name == fieldName select f).FirstOrDefault(); if (null != field) { string[] groupNames = field.GroupName.Split(new string[] { "//" }, StringSplitOptions.RemoveEmptyEntries); // valid? if (groupNames.Length <= depth) { continue; } groupName = groupNames[depth]; groupName = ParseGroupName(groupName); } } // groupName found, try to find/create property as an array. if (null != groupName) { PropertyInfo group = type.GetProperty(groupName); if (null == group) { continue; } Type groupType = group.PropertyType; if (InfoPlusEntity.IsArray(groupType)) { // get element type Type elementType = groupType.IsGenericType ? groupType.GetGenericArguments()[0] : groupType.GetElementType(); for (int i = 0; i < arr.Length; i++) { object groupObject = group.GetValue(o, null); // 1. Create if (null == groupObject) { // Create one. if (groupType.IsArray) { groupType = elementType.MakeArrayType(); groupObject = Activator.CreateInstance(groupType, arr.Length); } else { // Generic Interface if (true == groupType.IsInterface) { groupType = typeof(List <>).MakeGenericType(elementType); } groupObject = Activator.CreateInstance(groupType); } group.SetValue(o, groupObject, null); } // 2.Resize if (groupType.IsArray) { var groupArray = ((Array)groupObject); int oldLength = groupArray.Length; // Resize & Clone if (oldLength < arr.Length) { MethodInfo method = typeof(Array).GetMethod("Resize"); MethodInfo generic = method.MakeGenericMethod(elementType); object[] args = new object[] { groupObject, arr.Length }; generic.Invoke(null, args); for (int n = 0; n < oldLength; n++) { ((Array)args[0]).SetValue(groupArray.GetValue(n), n); } groupObject = args[0]; group.SetValue(o, groupObject, null); } } groupObject = group.GetValue(o, null); groupType = groupObject.GetType(); Array ga = InfoPlusEntity.ObjectToArray(groupObject); object elementObject = null; // Load if (i < ga.Length) { elementObject = ga.GetValue(i); } IDictionary <string, object> d = new Dictionary <string, object>(); d.Add(key, arr.GetValue(i)); if (isName && null != a0) { d.Add(fieldName, a0.GetValue(i)); } string nextPath = path + "_" + i; InfoPlusEntity.Convert(d, fields, ref elementObject, depth, elementType, i, nextPath, external); // Save if (groupType.IsArray) { ((Array)groupObject).SetValue(elementObject, i); } else if (i >= ga.Length) { groupType.InvokeMember("Add", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, groupObject, new object[] { elementObject }); } } } } } } return(o); }