# Plugin.NET **Repository Path**: lijun.hu/Plugin.NET ## Basic Information - **Project Name**: Plugin.NET - **Description**: c#插件管理器 - **Primary Language**: C# - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 67 - **Created**: 2018-07-08 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Plugin.NET c#插件管理器。 当前版本仅支持接口(`interface`)依赖,即使用反射技术,根据接口来实现插件的依赖注入。 ## 运行环境 项目使用 .net 4.0 编写,自己随便改改代码就能用到.net2.0和.netcore上。 ## 使用方法 1. 编写程序的接口类,在入口项目中引用这个接口 2. 在程序中引用**Plugin.NET.dll** 3. 初始化插件管理器 4. 绑定插件管理器的事件`OnPlugin`,这个事件提供了丰富的插件加载数据 5. 调用 `Load` 方法加载已经存在的所有插件,这个方法可以传入一个过滤器函数 6. 如果希望插件可以热加载,那么再调用 `Watch` 方法,以监视插件目录是否有新的插件放进去 7. 如果要停止热加载,那么就调用 `StopWatch` 以停止 ## 示例 ```csharp class Program { static void Main(string[] args) { // 使用接口来实例化插件管理器 // 如果要对其它接口进行插件管理, // 那么可以创建另一个插件管理器的实例 var pluginManager = new PluginManager(); // 处理插件管理器发出的事件 pluginManager.OnPlugin += PluginManager_OnPlugin; // 加载插件目录下的所的插件 pluginManager.Load(); // 开始监视新放进目录的插件 pluginManager.Watch(); Console.WriteLine("正在监视插件目录变动,按`Enter`退出"); Console.ReadLine(); } /// /// 处理插件管理器发出的事件 /// /// 插件管理器的实例对象 /// 事件数据 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*