主要使用NatashaDomain类实例化的方法(源码位置:src\Natasha.Domain\Extension\NatashaDomainExtension.cs)
相关方法:
(相关资料图)
LoadPluginUseDefaultDependency如果加载的dll已经被加载过了,则跳过
LoadPluginWithAllDependency不会判断高低版本,源码中的解释是默认的,感觉和Default类似
LoadPluginWithHighDependency使用高版本的dll
LoadPluginWithLowDependency 使用低版本的dll
参数说明:
string path必填,dll所在路径
Func
? excludeAssembliesFunc = null选填,需要排除的dll,返回true为排除引用,例如共同引用某个公用的dll(例如Utils.dll),此时可以选择使用哪个版本的dll
找到class类(默认所有插件的实现类为*Controller),也可以按照下面例子来
var type = assembly.GetTypes().Where(item => item.Name.IndexOf("Controller")!=-1).First();
实例化
var plugin = (IPluginClass)(Activator.CreateInstance(type)!);
创建两个底层项目
IPluginBase项目:用于创建插件使用的接口
using PluginUtil;namespace IPluginBase{ public interface IPluginClass { /// /// 初始化方法 /// public void initialize(); /// /// 获得插件特有的方法 /// /// public List getFunction(); /// /// 获得需要定时方法 /// /// public List getTimeFunc(); /// /// 通过方法执行插件代码 /// /// FruitFunction /// 可能输入的数值 /// public String execute(FruitFunction function, String param); }}
PluginUtil项目,用于声明FruitFunction
using System.ComponentModel;namespace PluginUtil{ public enum FruitFunction { [Description("硬度")] hardness = 01, [Description("苹果特有功能")] appleAttr = 02, [Description("切")] cut = 03 }}
创建两个插件项目
PluginApple项目
using IPluginBase;using PluginUtil;namespace PluginApple{ public class PluginAppleClass : IPluginClass { public string execute(FruitFunction function, string param) { switch (function) { case FruitFunction.cut: Console.WriteLine("切苹果"); break; case FruitFunction.hardness: Console.WriteLine("苹果很脆"); break; case FruitFunction.appleAttr: Console.WriteLine("苹果特有属性"); break; } return "结束"; } public List getFunction() { Console.WriteLine("返回苹果的现有功能"); return new List() { FruitFunction.appleAttr, FruitFunction.cut, FruitFunction.hardness }; } public List getTimeFunc() { Console.WriteLine("返回苹果的定时功能"); return new List() { FruitFunction.cut}; } public void initialize() { Console.WriteLine("苹果初始化完成"); } }}
PluginBanana项目
using IPluginBase;using PluginUtil;namespace PluginBanana{ public class PluginBananaClass : IPluginClass { public string execute(FruitFunction function, string param) { switch (function) { case FruitFunction.cut: Console.WriteLine("切香蕉"); break; case FruitFunction.hardness: Console.WriteLine("香蕉很软"); break; } return "结束"; } public List getFunction() { Console.WriteLine("返回香蕉的现有功能"); return new List() { FruitFunction.cut, FruitFunction.hardness }; } public List getTimeFunc() { Console.WriteLine("返回香蕉的定时功能"); return new List() { FruitFunction.cut }; } public void initialize() { Console.WriteLine("香蕉初始化完成"); } }}
使用Natasha实现两个插件项目的方法
前置条件:将PluginApple.dll和PluginBanana.dll放到NatashaStudyConsole.exe同级下的plugins文件夹中
using IPluginBase;using PluginUtil;using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace NatashaStudyConsole{ internal class PluginDemo { public void PluginMethod() { //获得dll存放路径 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory+ "plugins"); //实例化NatashaDomain NatashaDomain domain = new(Guid.NewGuid().ToString()); List assemblies = new List(); //通过获得所有的dll来进行实例化 Directory.GetFiles(path, "*.dll").ToList().ForEach(dll => { //加载dll var assembly = domain.LoadPluginWithAllDependency(dll); // 本例子中项目名称为"A",需要实例化的类为"AClass",因此使用IndexOf方法 // 获得项目名称 var asmName = assembly.GetName().Name!; // 根据项目名称判断应该实例那个class var type = assembly.GetTypes().Where(item => item.Name.IndexOf(asmName)!=-1).First(); // 实例化 var plugin = (IPluginClass)(Activator.CreateInstance(type)!); if (plugin != null) { // 保存 assemblies.Add(plugin); } }); assemblies.ForEach(assembly => { // 实现相关方法 List functions = assembly.getFunction(); if(functions != null && functions.Count > 0) { assembly.execute(functions[0], ""); } }); } }}
代码结构示意图:
执行结果: