实现重载

This commit is contained in:
cli 2025-04-24 21:01:01 +08:00
parent 820773bac2
commit dbe31c87da
7 changed files with 274 additions and 8 deletions

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Reflection; using System.Reflection;
using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.FreeRedis;
using JiShe.CollectBus.IotSystems.Protocols; using JiShe.CollectBus.IotSystems.Protocols;
using JiShe.CollectBus.Protocol.Contracts.Interfaces; using JiShe.CollectBus.Protocol.Contracts.Interfaces;
using JiShe.CollectBus.Protocol.Contracts.Models; using JiShe.CollectBus.Protocol.Contracts.Models;
@ -22,10 +24,13 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IRepository<ProtocolInfo, Guid> _protocolInfoRepository; private readonly IRepository<ProtocolInfo, Guid> _protocolInfoRepository;
private readonly IFreeRedisProvider _redisProvider;
public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger) public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger)
{ {
_logger = logger; _logger = logger;
_protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>(); _protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>();
_redisProvider = serviceProvider.GetRequiredService<IFreeRedisProvider>();
} }
@ -42,7 +47,8 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name); await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name);
await _protocolInfoRepository.InsertAsync(Info); await _protocolInfoRepository.InsertAsync(Info);
//await _protocolInfoCache.Get() await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name);
await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info);
} }
public abstract Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null) where T :class; public abstract Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null) where T :class;

View File

@ -1,5 +1,6 @@
using JiShe.CollectBus.Protocol.Contracts.Interfaces; using JiShe.CollectBus.Protocol.Contracts.Interfaces;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -15,9 +16,30 @@ namespace JiShe.CollectBus.Protocol.Test
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{ {
Console.WriteLine("TestProtocolPlugin Initialization"); Console.WriteLine("TestProtocolPlugin OnApplicationInitializationAsync");
var protocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(TestProtocolPlugin)); var protocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(TestProtocolPlugin));
RemoveServiceAtRuntime(context.ServiceProvider);
await protocol.LoadAsync(); await protocol.LoadAsync();
} }
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
Console.WriteLine("TestProtocolPlugin OnApplicationShutdown");
base.OnApplicationShutdown(context);
}
public void RemoveServiceAtRuntime(IServiceProvider serviceProvider)
{
var services = serviceProvider.GetService<IServiceCollection>();
services?.AddKeyedSingleton<IProtocolPlugin, TestProtocolPlugin>(nameof(TestProtocolPlugin));
//var services = (IServiceCollection)serviceProvider.GetService(typeof(IServiceCollection));
//var pluginService = serviceProvider.GetKeyedService<IProtocolPlugin>(nameof(TestProtocolPlugin));
//if (services != null && pluginService!=null)
//{
// services.Remove(pluginService);
//}
}
} }
} }

View File

@ -20,7 +20,7 @@ namespace JiShe.CollectBus.Protocol.Test
{ {
} }
public sealed override ProtocolInfo Info => new(nameof(TestProtocolPlugin), "Test", "TCP", "Test协议", "DTS1980-Test"); public sealed override ProtocolInfo Info => new(nameof(TestProtocolPlugin), "Test", "TCP", "Test协议", "DTS1980-TEST");
public override Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null) public override Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null)
{ {

View File

@ -11,7 +11,6 @@ using Microsoft.Extensions.Logging;
using Serilog.Core; using Serilog.Core;
using System; using System;
using System.Reflection; using System.Reflection;
using TouchSocket.Core;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -21,7 +20,6 @@ namespace JiShe.CollectBus.Protocol
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Console.WriteLine("StandardProtocolPlugin ConfigureServices");
context.Services.AddKeyedSingleton<IProtocolPlugin, StandardProtocolPlugin>(nameof(StandardProtocolPlugin)); context.Services.AddKeyedSingleton<IProtocolPlugin, StandardProtocolPlugin>(nameof(StandardProtocolPlugin));
//RegisterProtocolAnalysis(context.Services); //RegisterProtocolAnalysis(context.Services);
LoadAnalysisStrategy(context.Services); LoadAnalysisStrategy(context.Services);
@ -29,11 +27,17 @@ namespace JiShe.CollectBus.Protocol
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
{ {
Console.WriteLine("StandardProtocolPlugin Initialization"); Console.WriteLine("StandardProtocolPlugin OnApplicationInitializationAsync");
var standardProtocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(StandardProtocolPlugin)); var standardProtocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(StandardProtocolPlugin));
await standardProtocol.LoadAsync(); await standardProtocol.LoadAsync();
} }
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
Console.WriteLine("StandardProtocolPlugin OnApplicationShutdown");
base.OnApplicationShutdown(context);
}
public void LoadAnalysisStrategy(IServiceCollection services) public void LoadAnalysisStrategy(IServiceCollection services)
{ {
var assembly = Assembly.GetExecutingAssembly(); var assembly = Assembly.GetExecutingAssembly();

View File

@ -23,11 +23,13 @@ using JiShe.CollectBus.IotSystems.MessageReceiveds;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection;
using Cassandra; using Cassandra;
using JiShe.CollectBus.Interceptors; using JiShe.CollectBus.Interceptors;
using JiShe.CollectBus.IotSystems.Protocols; using JiShe.CollectBus.IotSystems.Protocols;
using TouchSocket.Core; using TouchSocket.Core;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using JiShe.CollectBus.DynamicModule;
namespace JiShe.CollectBus.Samples; namespace JiShe.CollectBus.Samples;
@ -39,18 +41,20 @@ public class TestAppService : CollectBusAppService
private readonly ICassandraProvider _cassandraProvider; private readonly ICassandraProvider _cassandraProvider;
private readonly IProtocolService _protocolService; private readonly IProtocolService _protocolService;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IDynamicModuleManager _dynamicModuleManager;
public TestAppService( public TestAppService(
ILogger<TestAppService> logger, ILogger<TestAppService> logger,
ICassandraRepository<MessageIssued, string> messageReceivedCassandraRepository, ICassandraRepository<MessageIssued, string> messageReceivedCassandraRepository,
ICassandraProvider cassandraProvider, IProtocolService protocolService,IServiceProvider serviceProvider) ICassandraProvider cassandraProvider, IProtocolService protocolService,IServiceProvider serviceProvider, IDynamicModuleManager dynamicModuleManager)
{ {
_logger = logger; _logger = logger;
_messageReceivedCassandraRepository = messageReceivedCassandraRepository; _messageReceivedCassandraRepository = messageReceivedCassandraRepository;
_cassandraProvider = cassandraProvider; _cassandraProvider = cassandraProvider;
_protocolService = protocolService; _protocolService = protocolService;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_dynamicModuleManager = dynamicModuleManager;
} }
public async Task AddMessageOfCassandra() public async Task AddMessageOfCassandra()
{ {
@ -146,6 +150,9 @@ public class TestAppService : CollectBusAppService
// 重新加载插件方法 // 重新加载插件方法
public async Task ReloadPluginsAsync() public async Task ReloadPluginsAsync()
{ {
//_serviceProvider.GetService<>() var aa = Assembly.LoadFile(
@"D:\Codes\CollectBusV5\JiShe.CollectBus\web\JiShe.CollectBus.Host\bin\Debug\net8.0\Plugins\JiShe.CollectBus.Protocol.Test.dll");
var module = aa.GetTypes().First(a=> typeof(IAbpModule).IsAssignableFrom(a));
await _dynamicModuleManager.ReinitializeModuleAsync(module);
} }
} }

View File

@ -0,0 +1,182 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
namespace JiShe.CollectBus.DynamicModule
{
/// <summary>
/// 动态模块管理器的实现
/// </summary>
public class DynamicModuleManager : IDynamicModuleManager, ISingletonDependency
{
private readonly IModuleContainer _moduleContainer;
private readonly IServiceProvider _serviceProvider;
public DynamicModuleManager(
IModuleContainer moduleContainer,
IServiceProvider serviceProvider)
{
_moduleContainer = moduleContainer;
_serviceProvider = serviceProvider;
}
public Type[] GetRegisteredModuleTypes()
{
return _moduleContainer.Modules.Select(m => m.Type).ToArray();
}
public async Task InitializeModuleAsync(Type moduleType)
{
//if (!typeof(IAbpModule).IsAssignableFrom(moduleType))
//{
// throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType));
//}
//var module = (IAbpModule)Activator.CreateInstance(moduleType);
//// 配置服务
//var configureServicesMethod = moduleType.GetMethod("ConfigureServices",
// BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
//if (configureServicesMethod != null)
//{
// var serviceConfigurationContext = CreateServiceConfigurationContext();
// configureServicesMethod.Invoke(module, new object[] { serviceConfigurationContext });
//}
//await CallModuleMethodAsync(module, "OnApplicationInitializationAsync", new object[] { new ApplicationInitializationContext(_serviceProvider) });
}
public async Task ReinitializeModuleAsync(Type moduleType)
{
if (!typeof(IAbpModule).IsAssignableFrom(moduleType))
{
throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType));
}
var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type.Name == moduleType.Name);
if (moduleDescriptor == null)
{
throw new InvalidOperationException($"找不到类型为 {moduleType.FullName} 的模块");
}
var module = moduleDescriptor.Instance;
await CallModuleMethodAsync(module, "OnApplicationShutdown", new object[] { new ApplicationShutdownContext(_serviceProvider) });
//var configureServicesMethod = moduleType.GetMethod("ConfigureServices",
// BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
//if (configureServicesMethod != null)
//{
// var serviceConfigurationContext = CreateServiceConfigurationContext();
// configureServicesMethod.Invoke(module, new object[] { serviceConfigurationContext });
//}
await CallModuleMethodAsync(module, "OnApplicationInitializationAsync", new object[] { new ApplicationInitializationContext(_serviceProvider) });
}
public async Task UnloadModuleAsync(Type moduleType)
{
if (!typeof(IAbpModule).IsAssignableFrom(moduleType))
{
throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType));
}
var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type.Name == moduleType.Name);
if (moduleDescriptor == null)
{
throw new InvalidOperationException($"找不到类型为 {moduleType.FullName} 的模块");
}
var module = moduleDescriptor.Instance;
await CallModuleMethodAsync(module, "OnApplicationShutdown", new object[] { new ApplicationShutdownContext(_serviceProvider) });
moduleDescriptor.GetType().GetProperty("IsUnloaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?
.SetValue(moduleDescriptor, true);
}
public bool IsModuleLoaded(Type moduleType)
{
var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type == moduleType);
if (moduleDescriptor == null)
{
return false;
}
// 检查模块是否已被标记为卸载
var isUnloaded = (bool?)moduleDescriptor.GetType().GetProperty("IsUnloaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?
.GetValue(moduleDescriptor) ?? false;
return !isUnloaded;
}
public Type GetModuleTypeByName(string moduleName)
{
return _moduleContainer.Modules
.FirstOrDefault(m => m.Type.Name == moduleName || m.Type.FullName == moduleName)?
.Type;
}
private async Task CallModuleMethodAsync(IAbpModule module, string methodName, object[] parameters)
{
var method = module.GetType().GetMethod(methodName);
if (method == null)
{
return;
}
if (method.ReturnType == typeof(Task))
{
await (Task)method.Invoke(module, parameters);
}
else
{
method.Invoke(module, parameters);
}
}
private ServiceConfigurationContext CreateServiceConfigurationContext()
{
// 反射获取内部构造函数
var contextType = typeof(ServiceConfigurationContext);
var constructor = contextType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault();
if (constructor != null)
{
// 创建新的服务集合并添加现有服务
var services = new ServiceCollection();
foreach (var service in ((IServiceCollection)_serviceProvider.GetService<IServiceCollection>()) ?? new ServiceCollection())
{
services.Add(service);
}
return (ServiceConfigurationContext)constructor.Invoke(new object[] { services });
}
// 如果反射失败,使用备选方案
try
{
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
var services = new ServiceCollection();
var context = Activator.CreateInstance(contextType, bindingFlags, null, null, null);
var servicesProperty = contextType.GetProperty("Services");
servicesProperty?.SetValue(context, services);
return (ServiceConfigurationContext)context;
}
catch
{
throw new InvalidOperationException("无法创建ServiceConfigurationContext。这可能是由于与ABP框架版本不兼容造成的。");
}
}
}
}

View File

@ -0,0 +1,45 @@
using System;
using System.Threading.Tasks;
namespace JiShe.CollectBus.DynamicModule
{
/// <summary>
/// 提供动态管理ABP模块的功能
/// </summary>
public interface IDynamicModuleManager
{
/// <summary>
/// 获取已注册的模块类型
/// </summary>
/// <returns>当前应用程序中已注册的所有模块类型</returns>
Type[] GetRegisteredModuleTypes();
/// <summary>
/// 重新初始化指定的模块
/// </summary>
/// <param name="moduleType">要重新初始化的模块类型</param>
/// <returns>表示异步操作的任务</returns>
Task ReinitializeModuleAsync(Type moduleType);
/// <summary>
/// 卸载指定的模块
/// </summary>
/// <param name="moduleType">要卸载的模块类型</param>
/// <returns>表示异步操作的任务</returns>
Task UnloadModuleAsync(Type moduleType);
/// <summary>
/// 检查模块是否已加载
/// </summary>
/// <param name="moduleType">要检查的模块类型</param>
/// <returns>如果模块已加载则为true否则为false</returns>
bool IsModuleLoaded(Type moduleType);
/// <summary>
/// 根据模块名称获取模块类型
/// </summary>
/// <param name="moduleName">模块名称</param>
/// <returns>模块类型如果找不到则为null</returns>
Type GetModuleTypeByName(string moduleName);
}
}