[新增]第一版
This commit is contained in:
parent
c8b39771a0
commit
49114b711e
21
你好插件/你好命令.cs
Normal file
21
你好插件/你好命令.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using PluginBase;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace 你好插件
|
||||||
|
{
|
||||||
|
public class 你好命令 : ICommand
|
||||||
|
{
|
||||||
|
public string 名称 { get => "你好"; }
|
||||||
|
public string 描述 { get => "显示一个你好的消息"; }
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]//引入命名空间
|
||||||
|
public static extern bool Beep(int frequency, int duration);
|
||||||
|
public int 执行()
|
||||||
|
{
|
||||||
|
Console.WriteLine("你好 !!!\n");
|
||||||
|
Beep(700, 200);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
你好插件/你好插件.csproj
Normal file
16
你好插件/你好插件.csproj
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\加载dll\加载dll.csproj">
|
||||||
|
<Private>False</Private>
|
||||||
|
<ExcludeAssets>runtime</ExcludeAssets>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.4.33403.182
|
VisualStudioVersion = 17.4.33403.182
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "加载dll", "加载dll\加载dll.csproj", "{4E443C0A-8E49-4186-9069-9946B033135E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "加载dll", "加载dll\加载dll.csproj", "{4E443C0A-8E49-4186-9069-9946B033135E}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "你好插件", "你好插件\你好插件.csproj", "{748E79C2-35E6-4B25-890A-B88064B47705}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -15,6 +17,10 @@ Global
|
|||||||
{4E443C0A-8E49-4186-9069-9946B033135E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4E443C0A-8E49-4186-9069-9946B033135E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4E443C0A-8E49-4186-9069-9946B033135E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4E443C0A-8E49-4186-9069-9946B033135E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{4E443C0A-8E49-4186-9069-9946B033135E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4E443C0A-8E49-4186-9069-9946B033135E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{748E79C2-35E6-4B25-890A-B88064B47705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{748E79C2-35E6-4B25-890A-B88064B47705}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{748E79C2-35E6-4B25-890A-B88064B47705}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{748E79C2-35E6-4B25-890A-B88064B47705}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
16
加载dll/PluginBase.cs
Normal file
16
加载dll/PluginBase.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PluginBase
|
||||||
|
{
|
||||||
|
public interface ICommand
|
||||||
|
{
|
||||||
|
string 名称 { get; }//Name
|
||||||
|
string 描述 { get; }//Description
|
||||||
|
|
||||||
|
int 执行();
|
||||||
|
}
|
||||||
|
}
|
113
加载dll/Program.cs
113
加载dll/Program.cs
@ -1,11 +1,118 @@
|
|||||||
namespace 加载dll
|
using PluginBase;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using 加载dll;
|
||||||
|
|
||||||
|
namespace 加载Dll
|
||||||
{
|
{
|
||||||
internal class Program
|
class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Hello, World!");
|
try
|
||||||
|
{
|
||||||
|
if (args.Length == 1 && args[0] == "/d")
|
||||||
|
{
|
||||||
|
Console.WriteLine("按下任何按钮开始运行...");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从插件加载指令
|
||||||
|
string[] pluginPaths = new string[]
|
||||||
|
{
|
||||||
|
"D:\\插件\\你好插件.dll",
|
||||||
|
"C:\\Users\\misaka20001\\source\\repos\\加载dll\\你好插件\\bin\\Debug\\net6.0\\你好插件.dll"
|
||||||
|
// Paths to plugins to load.
|
||||||
|
// 这里填写需要加载插件的路径
|
||||||
|
};
|
||||||
|
|
||||||
|
IEnumerable<ICommand> commands = pluginPaths.SelectMany(pluginPath =>
|
||||||
|
{
|
||||||
|
Assembly pluginAssembly = 加载插件(pluginPath);
|
||||||
|
return 创建命令(pluginAssembly);
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
if (args.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("命令: ");
|
||||||
|
// 输出加载的命令.
|
||||||
|
foreach (ICommand command in commands)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{command.名称}\t - {command.描述}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (string commandName in args)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"-- {commandName} --");
|
||||||
|
|
||||||
|
// Execute the command with the name passed as an argument.
|
||||||
|
// 使用作为参数传递的名称执行命令
|
||||||
|
ICommand? command = commands.FirstOrDefault(c => c.名称 == commandName);
|
||||||
|
if (command == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("没有找到任何已知命令");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
command.执行();
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Assembly 加载插件(string 相对路径)
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();//未实现异常
|
||||||
|
string? root = Path.GetFullPath(Path.Combine(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(path:typeof(Program).Assembly.Location)))))));
|
||||||
|
|
||||||
|
string pluginLocation = Path.GetFullPath(Path.Combine(root, 相对路径.Replace('\\', Path.DirectorySeparatorChar)));
|
||||||
|
Console.WriteLine($"加载插件: {pluginLocation}");
|
||||||
|
加载插件上下文 loadContext = new 加载插件上下文(pluginLocation);
|
||||||
|
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<ICommand> 创建命令(Assembly 程序集)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
foreach (Type type in 程序集.GetTypes())
|
||||||
|
{
|
||||||
|
if (typeof(ICommand).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
ICommand result = Activator.CreateInstance(type) as ICommand;
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
yield return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
string availableTypes = string.Join(",", 程序集.GetTypes().Select(t => t.FullName));
|
||||||
|
throw new ApplicationException(
|
||||||
|
$"在{程序集.Location}的{程序集}中找不到实现了ICommand的任何可用类型\n"+
|
||||||
|
$"可用类型: {availableTypes}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
61
加载dll/加载插件上下文.cs
Normal file
61
加载dll/加载插件上下文.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using 加载Dll;
|
||||||
|
|
||||||
|
namespace 加载dll
|
||||||
|
{
|
||||||
|
|
||||||
|
class 加载插件上下文 : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private AssemblyDependencyResolver? _解析器;
|
||||||
|
|
||||||
|
public 加载插件上下文(string 插件路径)
|
||||||
|
{
|
||||||
|
_解析器 = new AssemblyDependencyResolver(插件路径);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Assembly? Load(AssemblyName 程序集名称)
|
||||||
|
{
|
||||||
|
string? 程序集路径 = _解析器?.ResolveAssemblyToPath(程序集名称);
|
||||||
|
if (程序集路径 != null)
|
||||||
|
{
|
||||||
|
return LoadFromAssemblyPath(程序集路径);//从路径加载程序集
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IntPtr LoadUnmanagedDll(string 非托管DLL名称)//重写加载非托管DLL方法
|
||||||
|
{
|
||||||
|
string? libraryPath = _解析器?.ResolveUnmanagedDllToPath(非托管DLL名称);//解析非托管类型DLL为路径
|
||||||
|
if (libraryPath != null)
|
||||||
|
{
|
||||||
|
return LoadUnmanagedDllFromPath(libraryPath);//从路径加载程序集
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Assembly LoadPlugin(string relativePath)
|
||||||
|
{
|
||||||
|
// Navigate up to the solution root
|
||||||
|
string root = Path.GetFullPath(Path.Combine(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(
|
||||||
|
Path.GetDirectoryName(typeof(Program).Assembly.Location)))))));
|
||||||
|
|
||||||
|
string pluginLocation = Path.GetFullPath(Path.Combine(root, relativePath.Replace('\\', Path.DirectorySeparatorChar)));
|
||||||
|
Console.WriteLine($"Loading commands from: {pluginLocation}");
|
||||||
|
加载插件上下文 loadContext = new 加载插件上下文(pluginLocation);
|
||||||
|
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user