【推荐】基于WebActivator的改进版本KudyStudio.Web.Activating讲解与源码下载
ActivationMethodAttribute,利用它们可以灵活地随时在你的程序集中注册 一个或多个 Appilcation_Start()前/后触发和Appilcation_End()前触发的处理事件。
可触发的函数目标定义如下:
/// <summary>
/// Specifies the targets to use for invoking activation methods.
/// </summary>
[Serializable]
public enum ActivationMethodTarget
{
/// <summary>
/// Provides expanded support for ASP.NET application pre-start.
/// </summary>
PreApplicationStart = 0x0,
/// <summary>
/// Provides expanded support for ASP.NET application post-start.
/// </summary>
PostApplicationStart,
/// <summary>
/// Provides expanded support for before ASP.NET application shutdown.
/// </summary>
PreApplicationEnd
}
先介绍ActivationMethodAttribute,这个属性允许你以 静态方法方式 来向程序集注册 一个或多个 触发函数,并指定触发 函数的目标 与 执行顺序 ,它的定义如下:
/// <summary>
/// Provides expanded support for application activation.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple= true )]
public sealed class ActivationMethodAttribute : OrderableAttribute
{
#region Constructors
/// <summary>
/// Initializes a new instance of the ActivationMethodAttribute class.
/// </summary>
/// <param name="type">An object that describes the type of the activation method.</param>
/// <param name="methodName">An empty parameter signature that has no return value.</param>
public ActivationMethodAttribute(Type type, string methodName)
: this (type, methodName, ActivationMethodTarget.PreApplicationStart)
{
}
/// <summary>
/// Initializes a new instance of the ActivationMethodAttribute class.
/// </summary>
/// <param name="type">An object that describes the type of the activation method.</param>
/// <param name="methodName">An empty parameter signature that has no return value.</param>
/// <param name="methodTarget">The method target for the associated activation method</param>
public ActivationMethodAttribute(Type type, string methodName, ActivationMethodTarget methodTarget)
{
type.ThrowsIfNull( "type" );
methodName.ThrowsIfNullOrEmpty( "methodName" );
if (!Enum.IsDefined( typeof (ActivationMethodTarget), methodTarget))
{
throw new ArgumentException( "The methodTarget is undefined." );
}
this .Type = type;
this .MethodName = methodName;
this .MethodTarget = methodTarget;
}
#endregion
#region Properties
/// <summary>
/// Gets the type that is returned by the associated activation method.
/// </summary>
public Type Type
{
get ;
private set ;
}
/// <summary>
/// Gets the associated activation method.
/// </summary>
public string MethodName
{
get ;
private set ;
}
/// <summary>
/// Gets or sets the method target for the associated activation method.
/// </summary>
public ActivationMethodTarget MethodTarget
{
get ;
set ;
}
#endregion
}
有了ActivationMethodAttribute属性其实可以满足基本需求了,但是ActivationAttribute属性能让你的代码组织更清晰,怎么说?因为注册触发函数时不需要传入函数名称,而且方便每个程式元件建立自己的实现类(实现IPreApplicationStart、IPostApplicationStart、IPreApplicationEnd中的一个或多个接口)而不和其它程式元件的注册事务混在一起。ActivationAttribute属性这个允许你以 实现接口方式 来向程序集注册 一个或多个 触发函数,并指定触发函数的 执行顺序 ,定义如下:
/// <summary>
/// Provides expanded support for application activation(s).
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple= true )]
public sealed class ActivationAttribute : OrderableAttribute
{
#region Constructors
/// <summary>
/// Initializes a new instance of the ActivationAttribute class.
/// </summary>
/// <param name="type">
/// An object that implements any activation interface (<see cref="IPreApplicationStart"/>,
/// <see cref="IPostApplicationStart"/>, <see cref="IPreApplicationEnd"/>).
/// </param>
public ActivationAttribute(Type type)
{
type.ThrowsIfNull( "type" );
this .Type = type;
}
#endregion
#region Properties
/// <summary>
/// Gets the type that implements any activation interface.
/// </summary>
public Type Type
{
get ;
private set ;
}
#endregion
}
重点的实现就是ActivationManager类的InvokeActivationMethods方法,代码如下:
private static void InvokeActivationMethods(ActivationMethodTarget target)
{
List<OrderableAttribute> allAttributes = new List<OrderableAttribute>();
// get all attributes
foreach (Assembly assembly in AppAssemblies.Concat(GetCodeAssemblies(target)))
{
allAttributes.AddRange(GetAttributes<ActivationMethodAttribute>(assembly).Cast<OrderableAttribute>());
allAttributes.AddRange(GetAttributes<ActivationAttribute>(assembly).Cast<OrderableAttribute>());
}
// handle all ordered attributes
foreach (OrderableAttribute attribute in allAttributes.OrderBy(attr => attr.Order))
{
// invokes static method activations
ActivationMethodAttribute methodAttribute = attribute as ActivationMethodAttribute;
if (methodAttribute != null && methodAttribute.MethodTarget == target)
{
MethodInfo method = methodAttribute.Type.GetMethod(methodAttribute.MethodName, StaticMethodBindingFlags);
if (method != null )
{
method.Invoke( null , null );
continue ; // continue next target
}
// method not found
throw new ApplicationException( string .Format( "The type {0} doesn't have a static method named {1}." , methodAttribute.Type, methodAttribute.MethodName));
}
// try next case:
// invokes activations of activation classes that implements any activation interface
ActivationAttribute classAttribute = attribute as ActivationAttribute;
if (classAttribute != null )
{
Type type = classAttribute.Type;
object activation = null ;
if (IsValidActivationType(type))
{
try
{
activation = Activator.CreateInstance(type);
}
catch (Exception ex)
{
throw new ApplicationException( string .Format( "Fail to create instance of type {0}." , methodAttribute.Type), ex);
}
}
else
{
// invalid activation class
throw new ApplicationException( string .Format( "The type {0} is not a valid activation class." , type.FullName));
}
if (activation != null )
{
if (target == ActivationMethodTarget.PreApplicationStart && (activation is IPreApplicationStart))
{
(activation as IPreApplicationStart).PreApplicationStart();
}
else if (target == ActivationMethodTarget.PostApplicationStart && (activation is IPostApplicationStart))
{
(activation as IPostApplicationStart).PostApplicationStart();
}
else if (target == ActivationMethodTarget.PreApplicationEnd && (activation is IPreApplicationEnd))
{
(activation as IPreApplicationEnd).PreApplicationEnd();
}
}
}
}
}
.NET 4.0版本新增了一个 PreApplicationStartMethodAttribute 类只提供了一个开始的前触发支持,那怎么实现开始后触发和结束前触发呢?.Net4.0中提供了一个叫DynamicModuleUtility的类(位于Microsoft.Web.Infrastructure.dll程序集),里面只有一个方法RegisterModule(Type moduleType),利用它可以动态的添加HttpModule。WebActivator的作者就是巧妙的利用了动态注册HttpModule。在第一个处理触发事件的HttpModule初始化时触发PostApplicationStart,最后一个HttpModule销毁时触发PreApplicationEnd,核心原理就这么两点,比较简单,KudyStudio.Web.Activating里的源码并没有作优化,因为在应用程序周期只触发一次各个事件,没必要刻意的去代码加载速度什么的。 另外提醒一下,WebActivator1.5版本里的触发顺序只在每个独立程序集有效(不知道是不是作者故意的),KudyStudio.Web.Activating的触发顺序是在整个应用程序的全部程序集都有效的(有效是指排序的范围),感兴趣的朋友请下载源码分析。
下载 KudyStudio.Web.Activating.rar (.Net4.0)
在此再附上测试实例说明吧,ActivatingWeb网站项目中ActivatingTest.cs里写了触发函数的实现与注册,Global.asax是用于辅助测试的。运行网站的结果如下:
所有触发函数都按指定的顺序执行了,打开Web.config后点击保存,查看网站根目录下的ActivatingTest.txt内容为:
可以看到PreApplicationEnd触发函数也正常的按顺序执行了。
文章到此结束了,如果本文对你有帮助请 点击推荐 表示支持,谢谢,转载时请务必写明出处。
关于KudyStudio企业类库 :本人为公司写的一个功能性类库(主要Web方向,轻量的,Winform程序也可以使用),它主要包括网站开发中的常用功能如常用集合类、数据缓存(包括Memcached和Membase客户端)、数据库操作、自己定义配置管理、日志处理、数据压缩、数据加密、方法扩展、关键字过虑、简单图片处理、地址重写、网站表示层框架、各种功能性小框架等等等,远不止这些,目前还在整理完善中,大约在2012年底在公司项目完善时稳定初版本应该就会发布了,它可以免费提供给大家个人或商业使用,但此项目目前是不打算开源的, 谢绝索要源码 ,如果会开源自然就开源的。(请不要向本人发出攻击,相信没多少公司会把自己内部的产品源码发出去,能免费提供使用就很不错了,不是吗?)在最近一年内的开发整理中发布的关于KudyStudio的文章会或多或少提供一些源码分析,如果你想关注和使用此类库,请关注本博客。
工作室网站: www.kudystudio.com (未完成)
作者: Kudy
出处: http://kudy.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【分享】通用强大的主数据管理系统(最终分享版本)架构分析及源码下载
【MSH】一个轻量级但很实用的WCF模块服务框架+WCF模块服务托管程序MSH[开篇]
【分享】一个通用强大的主数据管理系统(架构设计讲解及源码下载)
KudySharp C#类库简要介绍
【分享】通用强大的主数据管理系统(最终分享版本)架构分析及源码下载
【MSH】如何开发第一个最简单的WCF模块服务(附实例源码)
【MSH】一个轻量级但很实用的WCF模块服务框架+WCF模块服务托管程序MSH[开篇]
【分享】一个通用强大的主数据管理系统(架构设计讲解及源码下载)
【MSH】如何开发第一个最简单的WCF模块服务(附实例源码)
【MSH】一个轻量级但很实用的WCF模块服务框架+WCF模块服务托管程序MSH[开篇]
【分享】一个通用强大的主数据管理系统(架构设计讲解及源码下载)
【jBox】2.3正式版 多功能jQuery对话框插件下载及常见使用问题解答
【jBox】 2.3 beta版 多功能jQuery对话框插件下载及常见使用问题解答
【jBox 2.2 beta版】一款基于 jQuery 的多功能对话框插件
实现SQL Server中的切割字符串SplitString函数
监控 SQL Server 的运行状况
高性能网站建设的14个原则
【jBox 2.2 beta版】一款基于 jQuery 的多功能对话框插件
【分享】一个通用强大的主数据管理系统(架构设计讲解及源码下载)
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于【推荐】基于WebActivator的改进版本KudyStudio.Web.Activating讲解的详细内容...