C#反射在模型与数据库赋值的时候的应用

C#反射在模型与数据库赋值的时候的应用

在这段时间的工作当中,公司给我安排了一个对接Ebay接口的任务,任务中出现了一个问题,就是Ebay的上传模型是一种复杂模型,里面模型一层嵌套一层,在C#转换的时候比较好处理,但是在把下载的数据存入数据库,或者是把数据库的数据序列化成上传模型就会有些问题。

我一开始的时候想到的是我可以直接把Ebay模型转换成Json字符串,然后放到数据库中。这个有优势也有缺点。

优点:

  1. 模型序列化反序列化方便

缺点

  1. 存储空间占用大
  2. 检索数据麻烦

在用了这个一段时间之后,我在想有没有更好的方式,来序列化数据,后来我想了一种新的方式来存储,模型就是一颗树,同一级的名字不一样,比方说 在下图中属性的值表示方法就是

dispalyName Name Value
属性1 .属性1 123
列表1 .属性2.列表[0] 123
子主题1 .属性3.子主题1

这样存储的话

好处:

  1. 可以直接检索某个节点的值
  2. 这个比上面的方法节省点空间

缺点:

  1. 实现起来麻烦
  2. 自定义规则,如果有字典类型的话,有点难以处理

以上是我对这个问题的思考

我现在实现了,数据类型转模型的赋值,下面是代码,模型转数据的还是比较简单的,顺着思路反写就可以了

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; }
}

猜你喜欢

转载自www.cnblogs.com/liwenqian/p/12730489.html