PostSharp应用:延迟加载(一)
PostSharp简介
引用PostSharp官方网站上的介绍:
PostSharp is a tool that can reduce the number of lines of code and improve its logical decoupling. Therefore its helps you delivering higher stability, cleaner design, and cheaper source code maintenance.
PostSharp是一个AOP框架,一个静态的AOP框架,它是在编译的时候把代码织入到您的代码中的。它是通过Attribute来标记需要静态织入代码的方法、成员以及类。PostSharp安装完成后,可以浏览它自带的例子来进行学习,我们这篇文章用它来做一个延迟加载的机制:
延迟加载
延迟加载简单地说,就是当你从数据库中加载一个对象的时候,该对象的属性并不是所有的都一次加载到内存中,有些属性需要用到的时候才从数据库中加载,这样可以减少同数据库的通讯量、降低数据库的查询压力(有些属性的获取是需要多表进行join才能获取的)等等。
先来看看使用AOP之前我的延迟加载的实现方式(c# 2.0),仍然是产品和产品分类类,产品类中的属性Category需要延迟加载:
public class Category { private int id; private string name; public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } } public class Product { private int id; private string name; private Category category; public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } public Category Category { get { return category; } set { category = value; } } }
1. 先定义2个委托用来获取2个方法,一个是获取单一关联属性,一个是获取列表关联属性的:
//单一关联属性加载 delegate LazyEntity LazyLoadEntity<Entity, LazyEntity>(Entity entity); //列表关联属性加载 delegate IList<LazyEntity> LazyLoadList<Entity, LazyEntity>(Entity entity);
2. 修改Product类的定义,增加如下的属性和方法:
private bool isCategoryLoaded = false; internal static LazyLoadEntity<Product, Category> LazyLoadCategory;
并且修改Product的Category的属性的get和set方法:
public Category Category { get { if(!isCategoryLoaded && category == null) { if(LazyLoadCategory != null) { category = LazyLoadCategory(this); isCategoryLoaded = true; } } return category; } set { isCategoryLoaded = true; category = value; } }
3. 在ProductManager类中构建一个根据一个产品的实例获取产品分类的方法并在一个静态的构造函数中赋值给LazyLoadCategory(当时使用的是典型的三层结构,Manager是业务逻辑层,多是静态方法):
public class ProductManager { static ProductManager() { Product.LazyLoadCategory = LazyLoadCategory; } static Category LazyLoadCategory(Product product) { ... } }
从上面可以看到构建一个延迟加载是多么的费事,需要写很多类似的代码,并且这个方法还有一个缺点就是如果你没有访问过ProductManager,那么你的Product的LazyLoadCategory将不会被赋值,你的延迟加载也就失效了。
引入PostSharp
引入了AOP之后,我们的延迟加载的代码看起来应该是这个样子的:
[LazyLoadClass] public class Product { private int id; private string name; [LazyLoadField("LazyLoadCategoryByProductId", "ProductService,LazyLoadSample")] private Category category; public int Id { get { return id; } set { id = value; } } public string Name { get { return name; } set { name = value; } } public Category Category { get { return category; } set { category = value; } } }是的,很简单,在类上标记[LazyLoadClass],然后再在需要延迟加载的属性对应的字段上标记[LazyLoadField(…)]就可以了,如何实现的呢?