延迟加载是一个很大的诱惑,可以达到一些比较好的效果,比如:

1、在实体框架中,由于关联数据的数量和使用时机是不确定的,通过延迟加载,仅在使用的时候去执行关联数据的查询操作,减少无谓的数据查询操作,可以降低单次数据查询执行的时间,提升系统的性能。

2、在一个插件平台中启动平台时只加载必需的程序集,当执行到具体插件时再加载插件相关的程序集,仅在需要的时候加载资源,可以减少插件平台的启动时间,使内存的占用更合理些。

延迟加载可以使资源的占用更加合理,并提升一定的性能,当然也有一些例子来说明延迟加载的坏处,这就需要根据实际的情况去考量,不是这篇文章的目的。

言归正传,在ASP.NET Web Forms开发模式中,程序集一般都放到bin目录下,或者在web.config中通过配置codebase或者probing节点指定程序集目录,应用程序启动时会从这些位置自动加载程序集。我们要使用延迟加载,就不能将程序集放到这些地方,将需要延迟加载的程序集放到一些有规则可循的目录是一种比较好的方式。比如:

root

|–bin

|–lazyload

|    |–bin1

|    |–bin2

将这些程序集都放到一个lazyload的目录中,然后在其中根据程序集的划分建立不同的子目录,根据需要去不同的目录中加载程序集。

那么使用什么方法加载程序集呢?

Assembly类提供了几个静态方法:Load、LoadFile、LoadFrom,可以通过这几个方法将dll文件加载到当前应用程序域的程序集中。

关于这几个方法如何选择,网上有一些总结,这里不做讨论。以下是一些总结:

http://www.cnblogs.com/xuqingfeng/archive/2012/05/22/assembly-load-loadfrom-loadfile-details.html

http://msdn.microsoft.com/zh-cn/library/dd153782(v=vs.110).aspx

实现程序集的延迟加载需要扩展两个地方:

1、依赖程序集的延迟加载

通过订阅当前应用程序域的AssemblyResolve事件,应用程序域在加载依赖程序集时如果找不到就会触发这个事件。

在这个事件中我们可以通过一些规则找到需要加载的程序集文件,然后通过Assembly的加载方法加载到内存,并返回。

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
 
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
 
//加载程序集部分省略
 
return assembly;
}

2、页面动态编译所需程序集的延迟加载

aspx页面在首次访问时会进行编译,编译时需要页面绑定的类所在的程序集。默认情况下这些程序集是在程序启动的时候自动加载的,从.net4开始,微软提供了一个应用程序启动的扩展支持System.Web.PreApplicationStartMethod,也可以在这里通过程序加载程序集,但还是达不到延迟加载的效果。

aspx页面的编译是通过BuildManager实现的,调用BuildManager.AddReferencedAssembly方法可以添加程序集,但是这个方法只能在上边提到的扩展支持中调用,程序启动后再调用就会抛出异常(可能是.net4.0还有些东西没协调好),此路不通。既然不能通过方法添加,那是不是可以直接加入到BuildManager的程序集集合中,很不幸全是私有的,有兴趣的可以自己反编译看看。

私有的其实也不是没有办法可以获取,使用反射,还好BuildManager有一个静态的属性TheBuildManager,通过反射获取这个属性的值就可以得到内部的BuildManager实例,修改程序集的集合就不成问题了。

// 获取BuildManager的实例
PropertyInfo buildmanagerProperty = Type.GetTypeFromHandle(typeof(BuildManager).TypeHandle).GetProperty("TheBuildManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty);
BuildManager buildmanager = buildmanagerProperty.GetValue(nullnullas BuildManager;
 
// 获取TopLevelReferencedAssemblies
PropertyInfo topLevelReferencedAssembliesProperty = Type.GetTypeFromHandle(typeof(BuildManager).TypeHandle).GetProperty("TopLevelReferencedAssemblies", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
IList assemblies = topLevelReferencedAssembliesProperty.GetValue(buildmanager, nullasIList;
 
// 添加程序集
Assembly assembly = null;
 
//加载程序集部分省略
 
assemblies.Add(assembly);

这段程序要在页面编译之前调用,比如PageHandlerFactory的GetHandler方法中。

通过这两个扩展基本上就可以实现程序集的延迟加载了,能用来干什么就要看自己了。博客园有个人搞了个OSGI.NET,就用到文中的两个方法。

当然上边只是初步给出了解决问题的方法,如果要实际使用,可能要考虑更多的问题,比如多线程同步问题、程序集多版本问题等等,有兴趣的可以写写看。

本人独立博客地址:http://blog.bossma.cn/dotnet/asp-net-how-to-lazy-load-assembly/

转载请注明出处。

ASP.NET Web Froms开发模式中实现程序集的延迟加载的更多相关文章

  1. Asp.Net Web API开发微信后台

    如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路. 需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful ...

  2. 微软实战训练营(X)重点班第(1)课:SOA必备知识之ASP.NET Web Service开发实战

    微软实战训练营 上海交大(A)实验班.(X)重点班 内部课程资料 链接:http://pan.baidu.com/s/1jGsTjq2 password:0wmf <微软实战训练营(X)重点班第 ...

  3. asp.net简述Web Forms开发模式

    详情请查阅:http://www.runoob.com/aspnet/aspnet-intro.html 1.Web Forms 是三种创建 ASP.NET 网站和 Web 应用程序的编程模式中的一种 ...

  4. ASP.NET MVC——CodeFirst开发模式

    Entity Framework框架提供了几种开发模式,比如Database First,Model First,Code First.Database First是最老也是应用得最广泛的一种设计方式 ...

  5. asp.net简述WP开发模式

    详情请参考菜鸟教程:http://www.runoob.com/aspnet/aspnet-tutorial.html 1.ASP.NET 是一个使用 HTML.CSS.JavaScript 和服务器 ...

  6. Java web MVC开发模式入门感悟

    当我进行第一个完整的java web项目的开发时,对以前所学的Java web知识体系有了一个清晰的进阶认识.我觉得非常有必要对此进行必要的总结. MVC,意指model(数据持久层)+viewer( ...

  7. ASP.NET Web Form和MVC中防止F5刷新引起的重复提交问题

    转载 http://www.cnblogs.com/hiteddy/archive/2012/03/29/Prevent_Resubmit_When_Refresh_Reload_In_ASP_NET ...

  8. ASP.NET Web API Basic Identity 中的基本身份验证

    缺点 用户凭证在请求中发送. 凭据作为明文发送. 每个请求都会发送凭据. 无法注销,除非结束浏览器会话. 易于跨站点请求伪造(CSRF); 需要反CSRF措施. 优点 互联网标准. 受所有主要浏览器支 ...

  9. asp.net简述MVC开发模式

    详情请参考:http://www.runoob.com/aspnet/mvc-intro.html 1.MVC 是三种 ASP.NET 编程模式中的一种.MVC 是一种使用 MVC(Model Vie ...

随机推荐

  1. 在Mac上通过Sublime、Skim编辑LaTeX

    转自:http://painterlin.com/2014/08/10/Using-LaTeX-with-Sublime-and-Skim-for-Mac.html Sublime Text是一款非常 ...

  2. JS实现复制到剪贴板

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  3. Oracle-Oracle10 数据空间建立,导入,导出--oracle10g 删除步骤

    --以system/manager身份登录SQLPlus,并执行 ========================管理员登陆==================================== 登 ...

  4. python 定制类

    看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的. __slots__我们已经知道怎么用了,__len__()方法我们也知道是为了能让cla ...

  5. Serializable在C#中的作用.net中的对象序列化 (转)

    序列化是指将对象实例的状态存储到存储媒体的过程,在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转 换为字节流,然后再把字节流写入数据流,在随后对对象进行反序列化时,将创建出 ...

  6. CGAffineTransform相关函数

    CoreGraphics.h CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI_2);
[xxx setTransform ...

  7. Unable to read TLD "META-INF/c.tld"错误

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  8. iOS stretchableImageWithLeftCapWidth 图片放大不变形

    转载自:http://www.cnblogs.com/bandy/archive/2012/04/25/2469369.html - (UIImage *)stretchableImageWithLe ...

  9. 理解 auto_ptr<T>

    1.auto_ptr<T>解决什么问题? 在堆上获取的资源,客户可能会忘记delete,或者由于异常没有执行到delete,导致资源泄漏.在栈上分配的对象,有个特点,不论出现什么情况,超出 ...

  10. MFC——AfxParseURL用法

    1.功能: 该函数解析URL字符串并返回服务的类型及组件,包含在 afxinet.h 头文件中. 2.定义 BOOL AFXAPI AfxParseURL(LPCTSTRpstrURL,DWORD&a ...