插件问题回答第4题

问题原贴: http://cloverprince.iteye.com/admin/blogs/481307

引用
4. 现有一个主程序用C#语言写成。现在要允许第三方开发人员编写扩展的类,约定第三方开发的类必须包含一个实现了某个已知接口(如interface IFooPlugin)的类,名称不限。如果要求第三方的类必须与主程序的二进制代码分开发布,把dll丢在某个文件夹内即可被动态装载使用,应如何实现?


回答:

每个插件作为一个程序集(Assembly),dll的形式。里面包含一个实现已知接口的类。使用Assembly.LoadFile()装载该插件,用Assembly.GetInterface()寻找程序集中实现了已知接口的类,用Activator.CreateInstance创建实例。


适用范围:

Mono2.0和Visual C# 2008中测试通过。反射机制自.NET 1.0开始就有。


实现:

先指定一个接口,比如叫Cloverprince.IPlugin。插件必须包含一个类,实现这个接口。
using System;

namespace Cloverprince
{
	public interface IPlugin
	{
		String Name {get;set;} // 设定和获取名字
		void Greet(); // 打招呼
	}
}



创建一个插件。插件包含一个类,实现这个接口。
这个类叫HelloWorldPlugin.HelloWorld。
using System;
using Cloverprince;

namespace HelloworldPlugin
{
	public class HelloWorld: Cloverprince.IPlugin
	{	
		private String _Name;
		public String Name {
			get {
				return _Name;
			}
			set {
				_Name = value;
			}
		}
		public void Greet() {
			Console.WriteLine("Hello, {0}",Name);
		}
	}
}

这个类将被编译成一个dll程序集


另一个插件也类似的制作。
类名:GoodbyePlugin.GoodbyeWorld:
using System;
using Cloverprince;

namespace GoodbyePlugin
{
	public class GoodbyeWorld: Cloverprince.IPlugin
	{	
		public String Name { get;set; }
		public void Greet() {
			Console.WriteLine("Goodbye, {0}",Name);
		}
	}
}

编译成另一个dll。


现在,两个插件已经有了,只差一个主程序来读取这两个插件了。
主程序:
using System;
using System.IO;
using System.Reflection;

using Cloverprince;

namespace Main
{
	class MainClass
	{
		private const String PLUGINS_PATH="plugins";
		public static void Main(string[] args)
		{
			foreach(String fileName in Directory.GetFiles(PLUGINS_PATH,"*.dll"))
			{
				Assembly ass = Assembly.LoadFile(Path.GetFullPath(fileName));
				foreach(Type t in ass.GetTypes()) {
					if(t.GetInterface("Cloverprince.IPlugin") != null) {
						IPlugin p = (IPlugin)Activator.CreateInstance(t);
					 	p.Name="Cloverprince";
						p.Greet();						
					}
				}
			}
		}
	}
}


以上,所有需要的文件齐备。


编译:

如上所述,每个插件编译成一个dll程序集,主程序随意。注意路径。


执行:

执行该程序需要的最小文件集(3个文件):
引用
.
|-- Main.exe
`-- plugins
    |-- GoodbyeWorld.dll
    `-- HelloworldPlugin.dll



执行:
Windows: Main  或者直接双击图标
Unix+Mono: mono Main.exe

引用
Goodbye, Cloverprince
Hello, Cloverprince



总结:
1. 主程序并不了解plugins目录中有多少插件。在运行时列举目录。
2. 主程序对每个plugins文件(比如叫HelloworldPlugin.dll)的了解只有:
- 这个程序集中有0个或多个类实现了IPlugin接口。
- 这个类拥有一个不带参数的构造方法。

你可能感兴趣的:(C++,c,windows,unix,C#)