代码改变世界

BlogEngine中的Extensinon实现

2011-03-17 09:28  MichaelYin  阅读(518)  评论(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接口使得继承的类可以自己实现添加相应的方法。

image

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);
                    }
                }
            }