延迟加载与序列化

简介: 如果使用了延迟加载(Lazy Load),那么,我们就会在序列化的时候碰到 延迟加载 变成了 “立即加载” 的问题。这是为什么呢,因为序列化器会去访问对象的属性,这就会导致属性的 get 方法内的代码被执行起来。

如果使用了延迟加载(Lazy Load),那么,我们就会在序列化的时候碰到 延迟加载 变成了 “立即加载” 的问题。这是为什么呢,因为序列化器会去访问对象的属性,这就会导致属性的 get 方法内的代码被执行起来。

比如,类型:

    class Test
    {
        public string Name {get; private set;}
        public PaperStrategy Paper
        {
            get
            {
                if (paper == null)
                {
                    paper = PaperStrategy.GetPaperByTest(this);
                }

                return paper;
            }
        }
    }

当返回给前台的时候,我们只需要返回 Name 属性就可以,但是,如果我们使用 JavaScriptSerializer (即 ASP.NET MVC 默认的 JSON 序列化器)的时候,序列化器会默认去遍历全部的属性,这就会导致业务上并不需要加载的 Paper 被序列化器自动加载了。

这是不能容忍的。解决方案有:

一:为属性加入 [ScriptIgnore]

即:

[ScriptIgnore]
public PaperStrategy Paper

Attribute ScriptIgnore 会通知 JavaScriptSerializer 不去序列化此属性,这样,就不会执行 get 中的代码;

不过,这带来一个问题,如果在别的请求中,又是需要这个属性的 Value ,该怎么办。所以,通过加 Attribute 来指导序列化并不可取。

 

二:构筑匿名类型

或者,我们在控制器中构筑匿名类型,如下,这就相当于存在一个转换过程,如果属性较多的话,就相对的编码烦多。

public class HomeController : SessionController
{
    public ActionResult Test(int id)
    {
        var test = Session.Get<Test>(id);

        return Json(new
        {
            test.Name
        }, JsonRequestBehavior.AllowGet);
    }
}

 

三:使用 ViewModel

如果我们觉得以上两种不合意,则可以强迫自己使用 ViewModel,即创建一个 TestDto,只包含需要序列化的字段,当然,这仍然需要一个类似 二 中的转换。不过,过多的实体类,不是我喜欢的,所以并不建议此种做法(如想减少实体类,请参看:减少到处衍生的实体类)。所以,大部分情况下,推荐的做法还是 构筑匿名类型 来达到 延迟加载 和 序列化 之间的平衡,除非我们有十分强烈的使用 ViewModel 的理由,比如:使用绑定。

 

参考:

http://stackoverflow.com/questions/6021934/json-lazyload

http://ayende.com/blog/4807/refactoring-toward-frictionless-odorless-code-the-case-for-the-view-model

Creative Commons License本文基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
目录
相关文章
|
SQL
延迟加载的底层原理知道吗?
延迟加载的底层原理知道吗?
96 0
|
算法 Java 容器
Java对象的序列化/反序列化原理及源码解析(中)
Java对象的序列化/反序列化原理及源码解析(中)
203 0
Java对象的序列化/反序列化原理及源码解析(中)
|
Java API 容器
Java对象的序列化/反序列化原理及源码解析(上)
Java对象的序列化/反序列化原理及源码解析(上)
366 0
Java对象的序列化/反序列化原理及源码解析(上)
|
存储 安全 Java
Java对象的序列化/反序列化原理及源码解析(下)
Java对象的序列化/反序列化原理及源码解析(下)
142 0
|
缓存
使用transient关键字解决ehcache序列化错误
使用Ehcache时发现个不起眼的小问题 在一个Model中有以下代码: public class MyModel implements Serializable { private static final long serialVersionUID = -990334519...
1324 0
|
存储 缓存 Java
Java对象的序列化和反序列化源码阅读
前言 序列化和反序列化看起来用的不多,但用起来就很关键,因为稍一不注意就会出现问题。序列化的应用场景在哪里?当然是数据存储和传输。比如缓存,需要将对象复刻到硬盘存储,即使断电也可以重新反序列化恢复。下面简单理解序列化的用法以及注意事项。
1157 0