Пример #1
0
        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);
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        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);
        }