c#插件管理器。
当前版本仅支持接口( interface
)依赖,即使用反射技术,根据接口来实现插件的依赖注入。
项目使用 .net 4.0 编写,自己随便改改代码就能用到.net2.0和.netcore上。
OnPlugin
,这个事件提供了丰富的插件加载数据 Load
方法加载已经存在的所有插件,这个方法可以传入一个过滤器函数 Watch
方法,以监视插件目录是否有新的插件放进去 StopWatch
以停止 class Program { static void Main(string[] args) { // 使用接口来实例化插件管理器 // 如果要对其它接口进行插件管理, // 那么可以创建另一个插件管理器的实例 var pluginManager = new PluginManager<IInterface>(); // 处理插件管理器发出的事件 pluginManager.OnPlugin += PluginManager_OnPlugin; // 加载插件目录下的所的插件 pluginManager.Load(); // 开始监视新放进目录的插件 pluginManager.Watch(); Console.WriteLine("正在监视插件目录变动,按`Enter`退出"); Console.ReadLine(); } /// <summary> /// 处理插件管理器发出的事件 /// </summary> /// <param name="sender">插件管理器的实例对象</param> /// <param name="e">事件数据</param> private static void PluginManager_OnPlugin(object sender, PluginEventArgs e) { switch (e.EventType) { // 加载程序集前的事件 case PluginEventTypes.AssemblyLoading: Console.WriteLine($"准备加载文件/"{e.FullName}/""); break; case PluginEventTypes.AssemblyLoaded: switch (e.ErrorType) { case PluginNET.error.PluginErrorTypes.None: Console.WriteLine($"从文件/"{e.FullName}/"加载程序集/"{e.Assembly.FullName}/"成功"); break; case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile: Console.WriteLine($"文件/"{e.FullName}/"不是有效的托管dll,可以查看异常:{e.Exception}"); break; case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.IllegalClassDefinition: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.InstanceCreateFailed: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.Unkown: // 这里不会出现这个类型 break; } break; case PluginEventTypes.ClassSearching: switch (e.ErrorType) { case PluginNET.error.PluginErrorTypes.None: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound: Console.WriteLine($"在文件/"{e.FullName}/"中没有找到实现了指定接口的类"); break; case PluginNET.error.PluginErrorTypes.IllegalClassDefinition: Console.WriteLine($"在文件/"{e.FullName}/"中找到了实现指定接口的类,但是其声明不是class或声明为abstract或不是public"); break; case PluginNET.error.PluginErrorTypes.InstanceCreateFailed: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.Unkown: // 这里不会出现这个类型 break; } break; case PluginEventTypes.InstanceCreated: switch (e.ErrorType) { case PluginNET.error.PluginErrorTypes.None: Console.WriteLine($"在文件/"{e.FullName}/"中找到了实现指定接口的类/"{e.ClassType}/",并且创建实例成功"); InvokePlugin(e.Instance); break; case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound: // 这里不会出现这个类型 break; case PluginNET.error.PluginErrorTypes.IllegalClassDefinition: Console.WriteLine($"在文件/"{e.FullName}/"中找到了实现指定接口的类,但是其声明不是class或声明为abstract或不是public"); break; case PluginNET.error.PluginErrorTypes.InstanceCreateFailed: Console.WriteLine($"在文件/"{e.FullName}/"中找到了实现指定接口的类/"{e.ClassType}/",但是创建实例时抛出了异常:{e.Exception}"); break; case PluginNET.error.PluginErrorTypes.Unkown: // 仅创建实例成功,但是结果却为null时会出现这个 Console.WriteLine($"在文件/"{e.FullName}/"中找到了实现指定接口的类/"{e.ClassType}/",创建实例成功,但是实例却是空引用(可能是不能转换成接口类型)"); break; } break; } } private static void InvokePlugin(object instance) { var plugin = instance as IInterface; Console.WriteLine(plugin.Method1()); Console.WriteLine(plugin.Method2("哈哈哈哈")); } }
示例请看解决方案中的 test 目录,测试项目为 Plugin.NETTest