183 lines
7.2 KiB
C#
183 lines
7.2 KiB
C#
|
|
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框架版本不兼容造成的。");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|