实现重载
This commit is contained in:
parent
820773bac2
commit
dbe31c87da
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using JiShe.CollectBus.Common.Consts;
|
||||
using JiShe.CollectBus.Common.Extensions;
|
||||
using JiShe.CollectBus.FreeRedis;
|
||||
using JiShe.CollectBus.IotSystems.Protocols;
|
||||
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
|
||||
using JiShe.CollectBus.Protocol.Contracts.Models;
|
||||
@ -22,10 +24,13 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IRepository<ProtocolInfo, Guid> _protocolInfoRepository;
|
||||
private readonly IFreeRedisProvider _redisProvider;
|
||||
|
||||
public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_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.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;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
@ -15,9 +16,30 @@ namespace JiShe.CollectBus.Protocol.Test
|
||||
|
||||
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
|
||||
{
|
||||
Console.WriteLine("TestProtocolPlugin Initialization");
|
||||
Console.WriteLine("TestProtocolPlugin OnApplicationInitializationAsync");
|
||||
var protocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(TestProtocolPlugin));
|
||||
RemoveServiceAtRuntime(context.ServiceProvider);
|
||||
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);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -11,7 +11,6 @@ using Microsoft.Extensions.Logging;
|
||||
using Serilog.Core;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using TouchSocket.Core;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Modularity;
|
||||
|
||||
@ -21,7 +20,6 @@ namespace JiShe.CollectBus.Protocol
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
Console.WriteLine("StandardProtocolPlugin ConfigureServices");
|
||||
context.Services.AddKeyedSingleton<IProtocolPlugin, StandardProtocolPlugin>(nameof(StandardProtocolPlugin));
|
||||
//RegisterProtocolAnalysis(context.Services);
|
||||
LoadAnalysisStrategy(context.Services);
|
||||
@ -29,11 +27,17 @@ namespace JiShe.CollectBus.Protocol
|
||||
|
||||
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
|
||||
{
|
||||
Console.WriteLine("StandardProtocolPlugin Initialization");
|
||||
Console.WriteLine("StandardProtocolPlugin OnApplicationInitializationAsync");
|
||||
var standardProtocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(StandardProtocolPlugin));
|
||||
await standardProtocol.LoadAsync();
|
||||
}
|
||||
|
||||
public override void OnApplicationShutdown(ApplicationShutdownContext context)
|
||||
{
|
||||
Console.WriteLine("StandardProtocolPlugin OnApplicationShutdown");
|
||||
base.OnApplicationShutdown(context);
|
||||
}
|
||||
|
||||
public void LoadAnalysisStrategy(IServiceCollection services)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
@ -23,11 +23,13 @@ using JiShe.CollectBus.IotSystems.MessageReceiveds;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Cassandra;
|
||||
using JiShe.CollectBus.Interceptors;
|
||||
using JiShe.CollectBus.IotSystems.Protocols;
|
||||
using TouchSocket.Core;
|
||||
using Volo.Abp.Modularity;
|
||||
using JiShe.CollectBus.DynamicModule;
|
||||
|
||||
namespace JiShe.CollectBus.Samples;
|
||||
|
||||
@ -39,18 +41,20 @@ public class TestAppService : CollectBusAppService
|
||||
private readonly ICassandraProvider _cassandraProvider;
|
||||
private readonly IProtocolService _protocolService;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IDynamicModuleManager _dynamicModuleManager;
|
||||
|
||||
|
||||
public TestAppService(
|
||||
ILogger<TestAppService> logger,
|
||||
ICassandraRepository<MessageIssued, string> messageReceivedCassandraRepository,
|
||||
ICassandraProvider cassandraProvider, IProtocolService protocolService,IServiceProvider serviceProvider)
|
||||
ICassandraProvider cassandraProvider, IProtocolService protocolService,IServiceProvider serviceProvider, IDynamicModuleManager dynamicModuleManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_messageReceivedCassandraRepository = messageReceivedCassandraRepository;
|
||||
_cassandraProvider = cassandraProvider;
|
||||
_protocolService = protocolService;
|
||||
_serviceProvider = serviceProvider;
|
||||
_dynamicModuleManager = dynamicModuleManager;
|
||||
}
|
||||
public async Task AddMessageOfCassandra()
|
||||
{
|
||||
@ -146,6 +150,9 @@ public class TestAppService : CollectBusAppService
|
||||
// 重新加载插件方法
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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框架版本不兼容造成的。");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user