add 动态添加dll

This commit is contained in:
zyxucp
2024-03-15 23:53:53 +08:00
parent dba98f7968
commit 277aacc34d
6 changed files with 92 additions and 16 deletions

View File

@@ -247,11 +247,6 @@
API调用秘钥
</summary>
</member>
<member name="P:AntSK.Domain.Repositories.Funs.Name">
<summary>
接口名称
</summary>
</member>
<member name="P:AntSK.Domain.Repositories.Funs.Path">
<summary>
接口描述

View File

@@ -1,8 +1,10 @@
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Loader;
using System.Xml;
using AntSK.Domain.Common;
using AntSK.Domain.Utils;
using System.Text.RegularExpressions;
namespace AntSK.Domain.Domain.Service
{
@@ -12,7 +14,8 @@ namespace AntSK.Domain.Domain.Service
private readonly Dictionary<string, (string Description, (Type ParameterType, string Description) ReturnType, (string ParameterName, Type ParameterType, string Description)[] Parameters)> _methodInfos;
private readonly IServiceProvider _serviceProvider;
private readonly Assembly[] _assemblies;
private Assembly[] _assemblies;
private readonly AssemblyLoadContext loadContext;
public FunctionService(IServiceProvider serviceProvider, Assembly[] assemblies)
{
@@ -20,6 +23,7 @@ namespace AntSK.Domain.Domain.Service
_methodInfos = [];
_serviceProvider = serviceProvider;
_assemblies = assemblies;
loadContext = new AssemblyLoadContext("AntSKLoadContext", true);
}
public Dictionary<string, MethodInfo> Functions => _methodCache;
@@ -48,11 +52,29 @@ namespace AntSK.Domain.Domain.Service
}
}
//动态加载部分
var loadedAssemblies = loadContext.Assemblies.ToList();
foreach (var assembly in loadedAssemblies)
{
// 从缓存中获取标记了ActionAttribute的方法
foreach (var type in assembly.GetTypes())
{
markedMethods.AddRange(type.GetMethods().Where(m =>
{
DescriptionAttribute da = (DescriptionAttribute)m.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
return da != null && da.Description == "AntSK";
}));
}
}
// 构建方法调用
foreach (var method in markedMethods)
{
var key = $"{method.DeclaringType.Assembly.GetName().Name}_{method.DeclaringType.Name}_{method.Name}";
_methodCache.TryAdd(key, method);
string pattern = "[^a-zA-Z0-9_]";
// 使用 '-' 替换非ASCII的正则表达式的字符
key = Regex.Replace(key, pattern, "_");
_methodCache.TryAdd(key, method);
var xmlCommentHelper = new XmlCommentHelper();
xmlCommentHelper.LoadAll();
@@ -63,8 +85,44 @@ namespace AntSK.Domain.Domain.Service
var parameters = method.GetParameters().Select(x => (x.Name, x.ParameterType, dict[x.Name])).ToArray();
var returnType = xmlCommentHelper.GetMethodReturnComment(method);
if (string.IsNullOrEmpty(description))
{
description = "导入插件";
}
_methodInfos.TryAdd(key, (description, (method.ReflectedType, returnType), parameters));
}
}
public void FuncLoad(string pluginPath)
{
try
{
if (File.Exists(pluginPath))
{
string directory = Path.GetDirectoryName(pluginPath);
string fileName = Path.GetFileName(pluginPath);
var resolver = new AssemblyDependencyResolver(directory);
// Create a custom AssemblyLoadContext
loadContext.Resolving += (context, assemblyName) =>
{
string assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
return context.LoadFromAssemblyPath(assemblyPath);
}
return null;
};
// Load your assembly
Assembly pluginAssembly = loadContext.LoadFromAssemblyPath(pluginPath);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
}
}
}
}

View File

@@ -10,12 +10,6 @@ namespace AntSK.Domain.Repositories
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
/// 接口名称
/// </summary>
[Required]
public string Name { get; set; }
/// <summary>
/// 接口描述
/// </summary>

View File

@@ -7,6 +7,10 @@ namespace AntSK.Test
/// </summary>
public class TestFunctionImport
{
/// <summary>
/// 获取名称
/// </summary>
/// <returns>返回名称</returns>
[Description("AntSK")]
public string GetName()
{

View File

@@ -3,6 +3,7 @@ using AntSK.Domain.Domain.Model.Fun;
using AntSK.Domain.Domain.Service;
using AntSK.Domain.Repositories;
using AntSK.Models;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.SemanticKernel;
@@ -50,7 +51,6 @@ namespace AntSK.Pages.ApiPage
}
foreach (var func in funList)
{
var methodInfo = _functionService.MethodInfos[func.Key];
list.Add(new FunDto() { Name = func.Key, Description = methodInfo.Description });
}
@@ -79,9 +79,11 @@ namespace AntSK.Pages.ApiPage
{
foreach (var file in fileList)
{
_funs_Repositories.Insert(new Funs() { Id = Guid.NewGuid().ToString(), Name = file.FileName, Path = file.FilePath });
_funs_Repositories.Insert(new Funs() { Id = Guid.NewGuid().ToString(), Path = file.FilePath });
_functionService.FuncLoad(file.FilePath);
}
_message.Info("上传成功");
await InitData("");
_fileVisible = false;
}
catch (System.Exception ex)

View File

@@ -44,7 +44,7 @@ builder.Services.AddScoped(sp => new HttpClient
builder.Services.Configure<ProSettings>(builder.Configuration.GetSection("ProSettings"));
builder.Services.AddServicesFromAssemblies("AntSK");
builder.Services.AddServicesFromAssemblies("AntSK.Domain");
builder.Services.AddSingleton(sp => new FunctionService(sp, [typeof(AntSK.App).Assembly, typeof(AntSK.Domain.Common.AntSkFunctionAttribute).Assembly]));
builder.Services.AddSingleton(sp => new FunctionService(sp, [typeof(AntSK.App).Assembly]));
builder.Services.AddScoped<FunctionTest>();
builder.Services.AddSwaggerGen(c =>
@@ -111,6 +111,7 @@ if (!app.Environment.IsDevelopment())
app.UseStaticFiles();
InitDB(app);
LoadFun(app);
app.UseRouting();
@@ -144,4 +145,26 @@ void InitDB(WebApplication app)
//创建vector插件如果数据库没有则需要提供支持向量的数据库
_repository.GetDB().Ado.ExecuteCommandAsync($"CREATE EXTENSION IF NOT EXISTS vector;");
}
}
void LoadFun(WebApplication app)
{
try
{
using (var scope = app.Services.CreateScope())
{
//codefirst 创建表
var funRep = scope.ServiceProvider.GetRequiredService<IFuns_Repositories>();
var functionService = scope.ServiceProvider.GetRequiredService<FunctionService>();
var funs= funRep.GetList();
foreach (var fun in funs)
{
functionService.FuncLoad(fun.Path);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " ---- " + ex.StackTrace);
}
}