static void SetValue(object o, string key, object val) { if (null == o || string.IsNullOrEmpty(key)) { return; } string fieldName, propertyName; bool isName = InfoPlusEntity.ParsePropertyName(key, out propertyName, out fieldName); // get right property PropertyInfo property = o.GetType().GetProperty(propertyName); if (null == property || false == property.CanWrite) { return; } var v = val; Type expect = property.PropertyType; string s = null == v ? string.Empty : v.ToString(); if (expect == typeof(CodeItem) || expect == typeof(InfoPlusUser)) { if (null == val || val.GetType() == typeof(string)) { object code = property.GetValue(o, null); if (null == code) { code = Activator.CreateInstance(expect); property.SetValue(o, code, null); } string propertyNameOfProperty = isName ? ((expect == typeof(CodeItem)) ? "CodeName" : "TrueName") : ((expect == typeof(CodeItem)) ? "CodeId" : "Account"); PropertyInfo propertyOfProperty = expect.GetProperty(propertyNameOfProperty); propertyOfProperty.SetValue(code, val, null); } } else if (!isName) // bypass _Name for atom types { if (null != val) { Type actual = val.GetType(); if (false == expect.Equals(actual)) { object parsed; bool result = InfoPlusEntity.TryParse(s, out parsed, expect); if (true == result) { v = parsed; } else { return; } } } // null val for value type? just do nothing. else if (true == expect.IsValueType) { return; } property.SetValue(o, v, null); } }
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); }