MVC系列(7) WebActivator的实现原理详解2015-01-08上篇文章,我们分析如何动态注册HttpModule的实现,本篇我们来分析一下通过上篇代码原理实现的WebActivator类库,WebActivator提供了3种功能,允许我们分别在HttpApplication初始化之前,之后以及ShutDown的时候分别执行指定的代码,示例如下:
[assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass1), "PreStart")][assembly: WebActivator.PostApplicationStartMethod(typeof(A.InitClass1), "PostStart")][assembly: WebActivator.ApplicationShutdownMethod(typeof(A.InitClass1), "ShutDown")]
另外还有一点和系统自带的PreApplicationStartMethodAttribute不同的是,WebActivator的每种特性都可以使用多次,比如:
[assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass1), "PreStart")][assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass2), "PreStart")][assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass3), "PreStart")]
因为它的源码很少,所以今天我们就来全面分析一下WebActivator的实现原理,首先下载WebActivator的最新1.5源码,源码地址:https://bitbucket.org/davidebbo/webactivator/src解压代码,我们可以看到WebActivator项目里总共有6个重要的cs文件,以及一个packages.config文件(用于标记本项目引用了Microsoft.Web.Infrastructure.dll类库),下面我们来分析一下每个文件的源码。3个XXXMethodAttribute属性:根据上面的用法,我们指导WebActivator提供了3个MethodAttribute,我们先来看看这3个文件都是如何实现的,查阅代码发现3个类(PreApplicationStartMethodAttribute/ PostApplicationStartMethodAttribute/ ApplicationShutdownMethodAttribute)的内容都是一样的,都是继承于 BaseActivationMethodAttribute类,然后提供构造函数所需要的Type类型和方法名称, 3个特性类都支持使用多次并且只能用于Assembly,代码如下:[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]通用的基类BaseActivationMethodAttribute:
using System;using System.Reflection;namespace WebActivator{// Base class of all the activation attributes[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]public abstract class BaseActivationMethodAttribute : Attribute{private Type _type;private string _methodName;public BaseActivationMethodAttribute(Type type, string methodName){_type = type;_methodName = methodName;}public Type Type { get { return _type; } }public string MethodName { get { return _methodName; } }public int Order { get; set; }public void InvokeMethod(){// Get the methodMethodInfo method = Type.GetMethod(MethodName,BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);if (method == null){throw new ArgumentException(String.Format("The type {0} doesn"t have a static method named {1}",Type, MethodName));}// Invoke itmethod.Invoke(null, null);}}}通过代码,我们首先可以看到,除了Type和MethodName以外,还多了一个Order属性,用来标记多次使用同一个Attribute的时候的执行顺序。然后提供了一个InvokeMethod方法,用来执行该类里传入当前Type类的MethodName静态方法。Assembly扩展方法AssemblyExtensions:
using System.Collections.Generic;using System.Linq;using System.Reflection;namespace WebActivator{static class AssemblyExtensions{// Return all the attributes of a given type from an assemblypublic static IEnumerable<T> GetActivationAttributes<T>(this Assembly assembly) where T : BaseActivationMethodAttribute{return assembly.GetCustomAttributes(typeof(T),inherit: false).OfType<T>();}}}