• asp.net web编程开发将model键值对化


    关键字:model属性,反射

    正文

            model是数据库的映射,在.net web开发中,作为程序的最底层。web开发的一切都是基于数据库的,分了层之后,就基于model了。

    为什么要将model键值对化呢?

            众所周知,程序里循环赋值当然比挨个赋值快的多,简单的多。web开发中,处理参数的接收时,往往是挨个字段都要写一个request请求,就像这样:

    string name = context.Request["name"];
    string pwd = context.Request["pwd"];
    string sex= context.Request["sex"];
    string tel = context.Request["tel"];
    string orderTimes = context.Request["orderTimes"];
    Model model = new Model();
    model.name = name;
    model.pwd = pwd;
    model.sex = sex;
    model.tel = tel;
    model.orderTimes = orderTimes;
    ....
    

    从上面可以看出,每一行只有字段的名称不一样,为什么不能写个循环呢?因此想当然的会这样写:

    for(int i=0;i<model.property.length;i++)
    {
    	property[i].name = context.Request[property[i].name];
    }
    

    这样写当然好啊
    1.如果增加一个字段,不用改代码。 2.不用复制粘贴多次。3.只要指定model,对所有的model都是通用的。

    这样写当然省事好多,可怎么做到将model键值对化呢,怎么去遍历一个类呢?

    键值对化只需要知道model类中各个属性的名称就行了,至于数据类型多种多样,c#中也有方法解决。


    使用反射和Dictionary将model类键值对化:

    第一步、构建model的键值对映射:

     public Dictionary<string, dynamic> map { get; set; }
    

    泛型的第一参数是属性的名称,第二个参数是对应的值。 这个值可以是int,string,bool等类型,只要使用c#中的dynamic关键字,就可以设置该类型在运行时在推断,和var关键字在编译时推断相反。简而言之,就是用dynamic关键字代替所有的类型,object也能做到,但是会有装箱和拆箱的效率问题,所以就没用。详细了解dynamic,请到msdn查看https://msdn.microsoft.com/zh-cn/library/dd264741.aspx

    其实循环遍历model也行啊,为什么要用map映射呢,原因在于:使用dynamic关键字,就避免了各种类型的手动转换了。
    第二步、通过反射得到一个model的各个属性的名称,注意是属性而不是字段,而且这里的属性名称一定要和数据库中的名称一样。

    代码如下:
    public Dictionary<string, dynamic> map { get; set; }
    
    Model model = new Model();
    Type modelType = model.GetType();
    
    foreach (var property in modelType.GetProperties())  //把所有属性名称加在map的key中
    {
         map.Add(property.Name, null);
    } 
    

    这时也不用再考虑给model的各个属性赋值,只需要让model的映射map处理参数接收,好处就在于,model遍历是反射,map遍历不是,而且model中
    不能为null的属性,这里map也能统一处理为null,好处就在于,页面传来的参数,赋值给map中对应的key的value,如果map中某一项为null,则代表前台没有这
    个参数传过来。

    public  void HttpRecieve(HttpContext context)
    {
         foreach(string key in map.Keys)
         {
             map[key] = context.Request[key] == "" ? null : context.Request[key];
         }
    }
    

    然而这样写是一定会错的:

    原因是c#中Dictionary 泛型不允许在遍历的时候修改遍历集合内的值。

    解决方法也很简单:增加一个List数组,遍历的时候遍历List,赋值的时候给Dictionary赋值。

    新增List集合定义:

    public List<string> modelNames;
    

    改写上面的初始化:

    public Dictionary<string, dynamic> map { get; set; }
    
    Model model = new Model();
    Type modelType = model.GetType();
    
    foreach (var property in modelType.GetProperties())  //把所有属性名称加在map的key中
    {
         map.Add(property.Name, null);
         modelNames.Add(property.Name);   //新增解决Dictionary不能遍历赋值
    }
    

    这样model的映射就完成了,这时,你就可以使用map做很多事了。
    给SqlParameter类型就很简单了,

    public List<SqlParameter> AddPms()
    {
         List<SqlParameter> pms = new List<SqlParameter>();
         foreach (string name in modelNames)
         {
             if (map.ContainsKey(name) && map[name] != null)
                  pms.Add(new SqlParameter("@" + name, map[name]));
         }
         return pms;
    }
    

    使用这个函数,就可以使用带参数的SQL语句,很方便的得到页面传来所有的参数。它是通用的,你不必考虑model里属性都叫什么名字,不用一个一个的
    复制粘贴。

    这里有个问题其实,上述方法处理的只是plain型的参数,如果是图片等文件类型的,可以在请求参数之后手动覆盖map,比如图片上传使用context.Request
    是接收不到的,这时只有在这些plain型数据后手动处理。一个表单plain类型多还是图片类型多呢_,是吧。

    注意这里没有说非法参数的过滤问题,如数字类型接收到的是字符串类型,肯定会报错啊。非法参数还是要处理的,这是几乎没法避免的,没有固定的范
    式,是简单的写个循环解决不了的。

    这一节,我们将model映射为map键值对了,下一节介绍将map映射回model的反射机制。

    ps: 反射真是个神奇的东西,能让程序变得简单好多。

  • 相关阅读:
    数据库——大事务
    数据库——性能理解
    java——通过GenericObjectPool获取到的资源,调用close()方法会close还是returnObject?
    gradle——入门
    MongoDB——morphia
    jvm——Java main方法的执行
    sql——limit
    阿里云Open API自动化脚本—ECS公网IP转化弹性公网IP
    阿里云共享带宽
    mysql5.x安装脚本
  • 原文地址:https://www.cnblogs.com/xiaoxuanzhi/p/4733280.html
Copyright © 2020-2023  润新知