asp.net插件实现

      还记得我在博客园第一篇博客就是学习委托和事件的学习笔记,呵呵,转眼已经在博客园待了一年多了,学到的东西确实是很多,感谢博客园里面辛勤写博的各位,给我们带来了宝贵的学习资料,传递着分享知识和技术的快乐。

      入正题,一直以来我都在寻求基于asp.net的插件的实现方式,有试过动态加载用户控件实现,感觉有些沉重,苦思很久,偶然之间想到了第一篇笔记,原来苦苦得寻求,却在灯火阑珊处,呵呵。其实插件主要是提供可拓展点,其实现实中的需求的插件所要实现的好像也只是拓展操作之前或者操作之后,有点像AOP,那如果程序能提供这些拓展点,插件功能就可以基本实现了!代码实现思路如下:

 1namespace MyPlug
 2{
 3    public class ArticleReadingArg : EventArgs
 4    {
 5        public Article TheArticle get;set;}
 6    }

 7    public class ArticlePage : System.Web.UI.Page
 8    {
 9        public static event EventHandler<ArticleReadingArg> OnReading;
10        protected override void OnInit(EventArgs e)
11        {
12            if (OnReading != null)
13            {
14                OnReading(EventArgs.Empty, new ArticleReadingArg(GetArticle(WebRequest.GetValue("ID"))));
15            }

16            base.OnInit(e);
17        }

18    }

 

首先是提供一个拓展点,假设我们要实现新闻管理系统的新闻访问统计插件,那我们要先提供一个可拓展点 代码如下这是一个页面的基类,他曝露出了一个静态的事件OnReading提供拓展者订阅页面浏览前的事件,当然,其实Page类也有很多事件可以订阅,不过并没有公开给其他类订阅或调用。好了,弄好这一步,基本条件已经成熟啦,因为外部类可以订阅到Onreading这个事件,并且可以时间的参数是可以访问到相对应的新闻实体,控制权就转移到订阅者手中了。

 1  public class CounterPlug
 2     {
 3         static CounterPlug()
 4         {
 5             if(this.Enable)ArticlePage.OnReading += AddCount;
 6         }
 7         public static void AddCount(object sender, ArticleReadingArg e)
 8         {
 9             e.TheArticle.Hit += 1;
10         }
11     }

 如果你用的asp.net模型是WebSite模型,那么很方便,利用本身带来的动态编译,可以很方便得实现后续的使用和管理,如果不是,可以编译成独立的dll,再利用反射创建实例,这里利用了.net静态初始化函数的特点-只在该类型的某个静态成员第一次被访问或该类型第一次实例化时执行,具体请查看msdn。我们这里用创建实例的形式激活这个静态函数,以达到事件的订阅。我们注意到插件加载是有条件的,这个条件可以根据配置文件,也可以根据数据库数据获取。下面是激活的简单代码,也就是你点击启用之后执行的

 Activator.CreateInstance<MyPlug.CounterPlug>();

 因为创建了一个实例,所以静态函数执行了,事件也被订阅了!所以插件的功能就会执行!

 静态变量的生命周期是随着应用程序的结束而结束的,所以应该不会冒冒然就消失了的。好啦,到这里就实现了插件的启用了,插件的卸载也挺取巧的,本来想到应用程序域这个概念,想想还是不妥,这玩意要一定的信任级别,最后想到webConfig每次修改都会重启应用程序,嘻嘻,这个本来很讨厌的特性,在这里还有得用,关闭插件时修改配置记录问Disenable之外,修改下WebConfig的最后修改时间

string configFile=HttpContext.Current.Server.MapPath("~/Web.config");

            System.IO.File.SetLastAccessTimeUtc(configFile,DateTime.UtcNow);

 可以达到重启的功能,这样实现也有不好的地方,每次插件卸载都要都会引起重新编译,确实不太好,不过系统也不是老是在加载卸载插件,主要是在不修改源代码的前提下进行拓展,目的确实实现了。如果你有更好的插件实现方式,不妨分享一下,期待。。。

posted @ 2008-11-10 23:05  Awen  阅读(4008)  评论(14编辑  收藏  举报