标签:
构建可扩展的应用程序时,接口是中心。可用基类来代替接口,但接口通常是首选的,因为它允许加载项开发人员选择他们自己的基类。例如,假如你要写一个应用程序,它能无缝的加载和使用别人创建的类型。下面描述了如何设计这样的应用程序。
注意: 可以使用MSCorlib.dll中定义的类型,因为CLR总是加载与CLR版本匹配的那个版本的MSCorlib.dll。此外,在一个CLR实例中,只会加载一个版本的MSCorlib.dll。换言之,永远不会出现多个版本的MSCorlib.dll都加载的情况。最后的结果是,绝不会出现类型版本不匹配的情况。这还有助于减少应用程序对内存的需求。
本节包含了一些非常重要的信息。跨程序集使用类型时,需要关注程序集的版本控制问题。要花一些时间精心构造,将用于跨程序集边界通信的类型隔离到他们自己的程序集中。要避免以后更改这些类型的定义。但是,如果真的要修改类型的定义,一定要修改程序集的版本号,并为新版本的程序集创建一个发布者策略文件。
下面看一个非常简单的例子,它综合运用了所有这些知识。首先是HostSDK程序集的代码:
namespace HostSDK.dll { public interface IAddIn { string DoSomething(Int32 x); } }
其次是AddInTypes.dll程序集中的代码,该程序集定义了两个公共类型,他们实现了HostSDK.dll的接口。为了生成这些程序集,必须引用HostSDK.dll程序集:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using HostSDK; namespace AddInTypes { public sealed class AddIn_A : IAddIn { public AddIn_A() { } public string DoSomething(Int32 x) { return "AddIn_A:" + x.ToString(); } } public sealed class AddIn_B : IAddIn { public AddIn_B() { } public string DoSomething(Int32 x) { return "AddIn_B:" + x.ToString(); } } }
然后就是一个简单的Host.exe程序集(一个控制台应用程序)的代码。为了生成这个程序集,它必须引用HostSDK.dll程序集。为了发现有哪些可用的加载项类型,以下宿主代码假定类型是在一个以dll文件扩展名的程序集中定义的,而且这个程序集已经部署到和宿主的EXE相同的目录中。Microsoft的“托管可扩展性框架”时在我刚才描素的各种机制的顶部构建的,它提供了加载项注册和发现机制,构建动态可扩展性应用程序时,强烈建议你研究一下MEF,它能简化本章描素的一些操作。
static void Main(string[] args) { String AddInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string[] AddInAssemblies = Directory.GetFiles(AddInDir, "*.dll"); List<Type> AddInTypes = new List<Type>(); foreach (String file in AddInAssemblies) { Assembly AddInAssembly = Assembly.LoadFrom(file); foreach (Type t in AddInAssembly.GetExportedTypes()) { //如果类型实现了IAddIn接口的一个类,该类就可以为宿主使用 if (t.IsClass && typeof(IAddIn).IsAssignableFrom(t)) { AddInTypes.Add(t); } } } foreach (Type t in AddInTypes) { IAddIn ai = (IAddIn)Activator.CreateInstance(t); Console.WriteLine(ai.DoSomething(5)); } }
这个简单的宿主和加载项例子没有用到AppDomain。但在实际应用程序中,可能在每个加载项自己的AppDomain中创建他们,每个AppDomain都有自己的安全性和配置设置。当然,如果将加载项从内存中移除,可以卸载相应的AppDomain。为了跨AppDomain边界通信,可告诉加载项开发人员从MashalByRefObject派生出他们自己的加载项类型。但是,另一个更常见的版本是让宿主应用程序定义自己的、从MashalByRefObject派生的内部类型。每个AppDomain创建好之后,宿主要在新的APPdomain中创建他们自己的MashalByRefObject派生类的实例。宿主的代码(位于默认AppDomain中)将和它自己的类型(位于其他AppDomain)通信,让后者载入加载项程序集,并创建和使用加载项程序集。
标签:
原文地址:http://www.cnblogs.com/bingbinggui/p/4575633.html