您的位置:首页 > 其它

创建插件框架(2)

2008-04-24 17:12 218 查看
创建插件框架(2)标题:Create a Plug-In FrameWork作者:Roy Osherove译者:easyjoy出处:MSDN Online,链接为http://msdn.microsoft.com/asp.net/archive/default.aspx?pull=/library/en-us/dnaspp/html/pluginframework.asp摘要:介绍如何为.Net应用程序添加插件支持,并提供一个用来框架例子。 代码下载:链接为http://download.microsoft.com/download/7/2/e/72e64769-58d2-4a91-9686-a1a160bb1bc8/CreatePluginFramework.msi 第四步:让应用程序找到新插件编译好插件后,如何让应用程序知道呢?解决办法很简单:(1)创建应用程序配置文件;(2)在配置文件中创建一项来列出所有插件;(3)创建解析器来解析该项; 要完成(1),只需向主程序添加一个XML文件。【Tip给该文件取名为App.Config,这样,每次编译程序的时候,Visual Studio.Net会自动把该文件复制到目标文件夹,并改名为<YourApp>.Config。 现在插件编写者可以很容易的往配置文件中添加一下。下面是这个配置文件的样子: <configuration><configSections> <section name="plugins" type="Royo.PluggableApp.PluginSectionHandler, PluggableApp" /></configSections> <plugins> <plugin type="Royo.Plugins.Custom.EmailPlugin, CustomPlugin" /> </plugins></configuration> 注意到configSections标签,该标签说明应用程序配置中有一个plugins项,而且有一个解析器专门解析plugins项。该解析器在类Royo.PluggableApp.PluginSectionHandler中,装配件的名字是PluggableApp。下一步中将展示这个类的代码。 接着,配置文件中有plugins标签,这列出所有的插件,包括类名和装配件名。 配置文件写好之后,就已经完成一半任务。剩下的是应用程序要读配置信息,并实例化插件。 第五步:用IConfigurationSectionHandler解析配置文件为了解析出配置文件中的插件信息,框架提供了一个很简单的机制,使得你可以注册一个类作为配置文件中某个特定部分的处理器。对于配置文件中的某个部分,如果框架不能解析,那么就需要一个专门的处理器;否则应用程序会抛出ConfigurationException。 为了提供解析plug-ins 项的类,需要实现下面这个接口,这个接口很简单,代码如下: //System.Configuration.IConfigurationSectionHandler,public interface IConfigurationSectionHandler{ public object Create(object parent, object configContext, System.Xml.XmlNode section);} 我们所要做的就是覆写Create方法,在这个方法中解析XML节点。在这里,要解析的节点是“Plugins”节点。这个类还需要有一个缺省的构造函数,这样框架可以动态实例化它。类的代码如下: public class PluginSectionHandler:IConfigurationSectionHandler{ public PluginSectionHandler() { } // Iterate through all the child nodes // of the XMLNode that was passed in and create instances // of the specified Types by reading the attribite values of the nodes // we use a try/Catch here because some of the nodes // might contain an invalid reference to a plugin type public object Create(object parent, object configContext, System.Xml.XmlNode section) { PluginCollection plugins = new PluginCollection(); foreach(XmlNode node in section.ChildNodes) { //Code goes here to instantiate //and invoke the plugins . . . } return plugins; }} 如前面提到的,你提供框架需要的信息来处理configSection标签中的plug-ins项,该项在时间的plug-ins标签之前。<configuration><configSections> <section name="plugins" type="Royo.PluggableApp.PluginSectionHandler, PluggableApp" /></configSections>... 看看上面是如何指定类的。对于的字符串有两部分组成,一个是类的全名(包括名字空间),逗号,所在的装配件。这就是框架用来实例化一个类所需要的信息,也是实例化一个插件所需要的信息。 实例化并调用插件OK,根据下面这段代码,我们该如何实例化插件呢?String ClassName = "Royo.Plugins.MyCustomPlugin, MyCustomPlugin"IPlugin plugin = (IPlugin )Activator.CreateInstance(Type.GetType(ClassName)); 这里发生了哪些事情呢:由于应用程序没有直接引用插件所在的装配件,所以必须要用System.Activator类。Activator是一个特殊的类,用来根据任意数量的参数来产生某个对象的实例。如果用过ASP或者Visual Basic,也许你记得用过CreateObject()函数,根据某个类的CLSID来实例化并返回某个对象。Activator也是同样的思路,只不过是用不同的参数,返回的是一个System.Object对象,而不是一个variant。 调用Activator的时候,传入的参数是一个类型(Type)。用Type.GetType()方法返回符合插件类型的类型的实例。注意Type.GetType()以plug-ins中的字符串作为参数,这个参数描述了所需要的类和装配件。 实例化插件后,要强制转换成IPlugin。这里需要一个Try-Catch块,这是为了确保类的确实现了IPlugin接口。获取接口实例后就保存下来,然后继续下一个XML节点。代码如下: public object Create(object parent, object configContext, System.Xml.XmlNode section){ //Derived from CollectionBase PluginCollection plugins = new PluginCollection(); foreach(XmlNode node in section.ChildNodes) { try { //Use the Activator class's 'CreateInstance' method //to try and create an instance of the plugin by //passing in the type name specified in the attribute value object plugObject = Activator.CreateInstance(Type.GetType(node.Attributes["type"].Value)); //Cast this to an IPlugin interface and add to the collection IPlugin plugin = (IPlugin)plugObject; plugins.Add(plugin); } catch(Exception e) { //Catch any exceptions //but continue iterating for more plugins } } return plugins;} 调用插件现在可以调用插件了。别忘了要传入一个IPluginContext参数。该参数包含插件正常工作所需要的信息。因此需要一个类实现该接口。代码如下:public interface IPluginContext{ string CurrentDocumentText{get;set;}} public class EditorContext:IPluginContext{ private string m_CurrentText= string.Empty; public EditorContext(string CurrentEditorText) { m_CurrentText = CurrentEditorText; } public string CurrentDocumentText {get{return m_CurrentText;} set{m_CurrentText = value;} }} 下面就可以调用插件了:private void ExecutePlugin(IPlugin plugin){ //create a context object to pass to the plugin EditorContext context = new EditorContext(txtText.Text); //The plugin Changes the Text property of the context plugin.PerformAction(context); txtText.Text= context.CurrentDocumentText; }} 总结(略) 【完】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: