BlogEngine中的Extensinon实现
2011-03-17 09:28 MichaelYin 阅读(519) 评论(0) 编辑 收藏 举报BlogEngine中提供了比较良好的扩展机制,用户可以通过添加Extension对BlogEngine进行各种功能的添加,而且还可以对各种扩展进行统一的管理,下面就把实现的机制和原理说明一下。
ManagedExtension这个类对应了BlogEngine中的Extension,ExtensionSettings是ManagedExtension中的配置信息,而ExtensionParameter则是ExtensionSettings下面的参数信息。需要说明一下的是这三个类都是能够Serializable的,每个Extension的相关的属性,配置信息,配置参数最后都被序列化成了一个XML字符串,存储在数据库中。
<?xml version="1.0" encoding="utf-16"?> <ManagedExtension xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="SendCommentMail"> <Version>1.3</Version> <Priority>0</Priority> <Description>Sends an e-mail to the blog owner whenever a comment is added</Description> <Author>BlogEngine.NET</Author> <AdminPage /> <Enabled>true</Enabled> <ShowSettings>true</ShowSettings> </ManagedExtension>
由于Extension和widget的配置信息都是写在一个数据表中,而且都是以序列化对象的方式,所以BlogEngine在这里也采用了一个相对通用的类结构设计。BlogEngine.Core.DataStore下的ExtensionSettings和WidgetSettings都继承自SettingsBase,而SettingsBase里面有ISettingsBehavior接口使得继承的类可以自己实现添加相应的方法。
ExtensionManager这个类提供了关于Extension所需要的管理的功能
BlogEngine中的Extension都有ExtensionAttribute,这样在运行的时候就可以通过反射读取Extension相应的一些信息,比如版本号,Description。
在项目运行的时候,Global.asax中调用Utils的LoadExtensions方法,该方法通过反射所有的程序集并且从中寻找有ExtensionAttribute的class,然后根据寻找的class到ExtensionManager中查找该Extension是否被启用,如果被启用的话则进行实例化,这样的话会首先执行Extension中的静态构造函数,这样的话Extension就会将处理的方法注册到相应的事件中,这样就完成了一个比较灵活的Extension机制。
ArrayList codeAssemblies = CodeAssemblies(); List<SortedExtension> sortedExtensions = new List<SortedExtension>(); foreach (Assembly a in codeAssemblies) { Type[] types = a.GetTypes(); foreach (Type type in types) { object[] attributes = type.GetCustomAttributes(typeof(ExtensionAttribute), false); foreach (object attribute in attributes) { if (attribute.GetType().Name == "ExtensionAttribute") { ExtensionAttribute ext = (ExtensionAttribute)attribute; sortedExtensions.Add(new SortedExtension(ext.Priority, type.Name, type.FullName)); } } } sortedExtensions.Sort(delegate(SortedExtension e1, SortedExtension e2) { if (e1.Priority == e2.Priority) return string.CompareOrdinal(e1.Name, e2.Name); return e1.Priority.CompareTo(e2.Priority); }); foreach (SortedExtension x in sortedExtensions) { if (ExtensionManager.ExtensionEnabled(x.Name)) { a.CreateInstance(x.Type); } } }