好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

【推荐】基于WebActivator的改进版本KudyStudio.Web.Activating讲解

【推荐】基于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讲解的详细内容...

  阅读:45次