Aplicación de la reflexión de C # en la asignación del modelo y la base de datos.

Aplicación de la reflexión de C # en la asignación del modelo y la base de datos.

Durante este período de trabajo, la compañía organizó una tarea para que yo interactuara con la interfaz de Ebay. Se produjo un problema en la tarea, es decir, el modelo de carga de Ebay es un modelo complejo, en el que el modelo se anida y se convierte en C # Es más fácil de tratar, pero habrá algunos problemas para almacenar los datos descargados en la base de datos o para serializar los datos de la base de datos en un modelo de carga.

Lo que pensé al principio era que podía convertir directamente el modelo de Ebay en una cadena Json, y luego ponerlo en la base de datos. Esto tiene ventajas y desventajas.

Ventajas:

  1. La serialización y deserialización del modelo son convenientes

Desventajas

  1. Gran espacio de almacenamiento
  2. Recuperar problemas de datos

Después de usar esto durante un tiempo, me preguntaba si había una mejor manera de serializar los datos. Más tarde, pensé en una nueva forma de almacenarlos. El modelo es un árbol y los nombres en el mismo nivel son diferentes, por ejemplo En la siguiente figura, el valor del atributo está representado por

dispalyName Nombre Valor
Atributo 1 Atributo 1 123
Listado 1 .Atributo 2. Lista [0] 123
Subtema 1 Atributo 3. Subtema 1

Si se almacena así

Beneficios:

  1. Puede recuperar directamente el valor de un nodo
  2. Esto ahorra un poco más de espacio que el método anterior.

Desventajas

  1. Engorroso de implementar
  2. Reglas personalizadas, si hay un tipo de diccionario, es un poco difícil de manejar

Lo anterior es mi pensamiento sobre este problema.

Ahora me he dado cuenta de que la asignación del tipo de datos al modelo es la siguiente, el código está debajo, el modelo a los datos es relativamente simple, solo siga la idea y escríbala nuevamente.

public class ModelHelper
{
    static Regex regex = new Regex(@"\.([a-zA-Z_\d]+)(\[(\d)\])?");
    public static T InitModel<T>(T rootModel, IEnumerable<KV> kVs)
        where T : new()
        {
            if (rootModel == null || kVs == null)
            {
                return rootModel;
            }

            foreach (var kv in kVs.OrderBy(a => a.Key))
            {
                if (!regex.IsMatch(kv.Key))
                {
                    continue;
                }
                //抓取所有符合格式的模型节点
                Queue<LevelModel> levelModels = new Queue<LevelModel>();
                var matches = regex.Matches(kv.Key);
                foreach (Match match in matches)
                {
                    var levelModel = new LevelModel()
                    {
                        Name = match.Groups[1].Value,//这个是节点名
                    };
                    if (!string.IsNullOrWhiteSpace(match.Groups[3]?.Value))
                    {
                        levelModel.Index = Convert.ToInt32(match.Groups[3]?.Value);//这个是节点索引
                    }
                    levelModels.Enqueue(levelModel);
                }

                UpdateData(rootModel.GetType(), rootModel, levelModels, kv.Value);
            }

            return rootModel;
        }

    public static object UpdateData(Type type, object data, Queue<LevelModel> levelModels, string value)
    {
        var levelModel = levelModels.Dequeue();//取出队列中的一个对象
        //var type= typeof(T);

        var prop = type.GetProperties().SingleOrDefault(a => a.Name.Equals(levelModel.Name));
        if (prop == null)//判断对象下面的属性有没有这个名字的,如果没有的话 就不用管了
        {
            return data;
        }

        try
        {
            if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))//如果是泛型
            {
                levelModel.Index = levelModel.Index ?? 0;
                var listData = prop.GetValue(data);
                var listType = prop.PropertyType;
                listData = InitList(listData, listType, levelModel.Index.Value);
                var getMethod = listType.GetMethod("get_Item");
                var setMethod = listType.GetMethod("set_Item");
                var childType = listType.GetGenericArguments()[0];
                var childData = getMethod.Invoke(listData, new object[] { levelModel.Index.Value });
                object val = null;
                if (levelModels.Count == 0)//没有下面的数值了,在这个属性里面是可以填写对象了
                {
                    val = GetValue(childType, value);
                    //childData = val;
                }
                else//如果下面还有层级的话,需要往下找
                {

                    var propData = childData ?? Activator.CreateInstance(childType);
                    val = UpdateData(prop.PropertyType, propData, levelModels, value);
                    //prop.SetValue(data, propData);
                }

                try
                {
                    setMethod.Invoke(listData, new object[] { levelModel.Index.Value, val });
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }

                prop.SetValue(data, listData);
            }
            else
            {
                if (levelModels.Count == 0)//没有下面的数值了,在这个属性里面是可以填写对象了
                {
                    var val = GetValue(prop.PropertyType, value);
                    prop.SetValue(data, val);
                    return data;
                }
                else//如果下面还有层级的话,需要往下找
                {

                    var propData = prop.GetValue(data) ?? Activator.CreateInstance(prop.PropertyType);
                    propData = UpdateData(prop.PropertyType, propData, levelModels, value);
                    prop.SetValue(data, propData);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }


        return data;
    }
    /// <summary>
    /// 初始化List对象
    /// </summary>
    /// <param name="obj">对象</param>
    /// <param name="type">List类型</param>
    /// <param name="num">最终的下标</param>
    /// <returns></returns>
    public static object InitList(object obj, Type type, int num)
    {
        if (type.GetGenericTypeDefinition() == typeof(List<>))
        {
            obj = obj ?? Activator.CreateInstance(type);//如果对象为空,创建之
            var countProp = type.GetProperties()
                .SingleOrDefault(a => a.Name.Equals("Count"));
            var count = (int)countProp.GetValue(obj);//获取List对象的长度

            var addMethod = type.GetMethod("Add");//获取List中的添加方法
            for (int i = count; i < num + 1; i++)
            {
                var argType = type.GetGenericArguments()[0];

                addMethod?.Invoke(obj, new[] { argType == typeof(string)?"":Activator.CreateInstance(argType) });
            }
        }

        return obj;
    }
    public static object GetValue(Type tp, string value)
    {
        try
        {
            if (tp.IsEnum)
            {
                if (!int.TryParse(value, out int val))
                {
                    return val;
                }
                else
                {
                    foreach (var enumValue in tp.GetEnumValues())
                    {
                        if (enumValue.ToString().Equals(value))
                        {
                            return enumValue;
                        }
                    }
                }



            }else if (tp == typeof(string))
            {
                return value;
            }
            else
            {
                var TryParse = tp.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder,
                                            new Type[] { typeof(string), tp.MakeByRefType() },
                                            new ParameterModifier[] { new ParameterModifier(2) });
                var parameters = new object[] { value, Activator.CreateInstance(tp) };


                bool success = (bool)TryParse.Invoke(null, parameters);
                if (success)
                {
                    return parameters[1];
                }

            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

        return Activator.CreateInstance(tp);
    }

    private void MyLogger(string message)
    {

    }
}

public class KV
{
    public string Key { get; set; }
    public string Value { get; set; }
}

public class LevelModel
{
    /// <summary>
    /// 名字
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 下标
    /// </summary>
    public int? Index { get; set; }
}

Supongo que te gusta

Origin www.cnblogs.com/liwenqian/p/12730489.html
Recomendado
Clasificación