mirror of
https://github.com/AIDotNet/AntSK.git
synced 2026-02-17 22:10:14 +08:00
add 动态添加dll
This commit is contained in:
@@ -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>
|
||||
接口描述
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -7,6 +7,10 @@ namespace AntSK.Test
|
||||
/// </summary>
|
||||
public class TestFunctionImport
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取名称
|
||||
/// </summary>
|
||||
/// <returns>返回名称</returns>
|
||||
[Description("AntSK")]
|
||||
public string GetName()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user