// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using PluginCore.AspNetCore.Extensions;
using PluginCore.AspNetCore.ResponseModel;
using PluginCore.Interfaces;
using System.Runtime.Loader;
namespace PluginCore.AspNetCore.Controllers;
///
/// [ASP.NET Core — 依赖注入\_啊晚的博客-CSDN博客\_asp.net core 依赖注入](https://blog.csdn.net/weixin_37648525/article/details/127942292)
/// [ASP.NET Core中的依赖注入(3): 服务的注册与提供 - Artech - 博客园](https://www.cnblogs.com/artech/p/asp-net-core-di-register.html)
/// [ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】 - Artech - 博客园](https://www.cnblogs.com/artech/p/asp-net-core-di-service-provider-1.html)
/// [dotnet/ServiceProvider.cs at main · dotnet/dotnet](https://github.com/dotnet/dotnet/blob/main/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs)
/// [Net6 DI源码分析Part2 Engine,ServiceProvider - 一身大膘 - 博客园](https://www.cnblogs.com/hts92/p/15800990.html)
/// [【特别的骚气】asp.net core运行时注入服务,实现类库热插拔 - 四处观察 - 博客园](https://www.cnblogs.com/1996-Chinese-Chen/p/16154218.html)
///
/// ActivatorUtilities.CreateInstance(serviceProvider, "test");
/// ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider);
///
[Route("api/plugincore/admin/[controller]/[action]")]
//[PluginCoreAdminAuthorize]
[ApiController]
[NonUnify]
public class DebugController : ControllerBase
{
#region Fields
private readonly IPluginContextManager _pluginContextManager;
#endregion Fields
#region Ctor
public DebugController(IPluginContextManager pluginContextManager)
{
_pluginContextManager = pluginContextManager;
}
#endregion Ctor
#region Actions
[HttpGet, HttpPost]
public async Task> PluginContexts()
{
BaseResponseModel responseModel = new BaseResponseModel();
try
{
var pluginContextList = _pluginContextManager.All();
Dictionary> keyValuePairs = new Dictionary>();
foreach (var pluginContext in pluginContextList)
{
keyValuePairs.Add($"{pluginContext.GetType().ToString()} - {pluginContext.PluginId} - {pluginContext.GetHashCode()}", pluginContext.Assemblies.Select(m => m.FullName).ToList());
}
responseModel.Code = 1;
responseModel.Message = "success";
responseModel.Data = keyValuePairs;
}
catch (Exception ex)
{
responseModel.Code = -1;
responseModel.Message = "error";
responseModel.Data = ex.ToString();
}
return await Task.FromResult(responseModel);
}
[HttpGet, HttpPost]
public async Task> AssemblyLoadContexts()
{
BaseResponseModel responseModel = new BaseResponseModel();
try
{
var assemblyLoadContextDefault = AssemblyLoadContext.Default;
var assemblyLoadContextAll = AssemblyLoadContext.All;
var responseDataModel = new AssemblyLoadContextsResponseDataModel();
responseDataModel.Default = new AssemblyLoadContextsResponseDataModel.AssemblyLoadContextModel
{
Name = assemblyLoadContextDefault.Name,
Type = assemblyLoadContextDefault.GetType().ToString(),
Assemblies = assemblyLoadContextDefault.Assemblies.Select(m => new AssemblyModel { FullName = m.FullName, DefinedTypes = m.DefinedTypes.Select(m => m.FullName).ToList() }).ToList()
};
responseDataModel.All = assemblyLoadContextAll.Select(item => new AssemblyLoadContextsResponseDataModel.AssemblyLoadContextModel
{
Name = item.Name,
Type = item.GetType().ToString(),
Assemblies = item.Assemblies.Select(m => new AssemblyModel { FullName = m.FullName, DefinedTypes = m.DefinedTypes.Select(m => m.FullName).ToList() }).ToList()
}).ToList();
responseModel.Code = 1;
responseModel.Message = "success";
responseModel.Data = responseDataModel;
}
catch (Exception ex)
{
responseModel.Code = -1;
responseModel.Message = "error";
responseModel.Data = ex.ToString();
}
return await Task.FromResult(responseModel);
}
[HttpGet, HttpPost]
public async Task> Assemblies()
{
BaseResponseModel responseModel = new BaseResponseModel();
try
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
List assemblyModels = new List();
foreach (var item in assemblies)
{
assemblyModels.Add(new AssemblyModel
{
FullName = item.FullName,
DefinedTypes = item.DefinedTypes.Select(m => m.FullName).ToList()
});
}
responseModel.Code = 1;
responseModel.Message = "success";
responseModel.Data = assemblyModels;
}
catch (Exception ex)
{
responseModel.Code = -1;
responseModel.Message = "error";
responseModel.Data = ex.ToString();
}
return await Task.FromResult(responseModel);
}
[HttpGet, HttpPost]
public async Task> Services([FromServices] IServiceProvider serviceProvider)
{
BaseResponseModel responseModel = new BaseResponseModel();
try
{
//IServiceProvider serviceProvider = HttpContext.RequestServices;
//var provider = serviceProvider.GetType().GetProperty("RootProvider", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//var serviceField = provider.GetType().GetField("_realizedServices", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//var serviceValue = serviceField.GetValue(provider);
//var funcType = serviceField.FieldType.GetGenericArguments()[1].GetGenericArguments()[0];
//ConcurrentDictionary> realizedServices = (ConcurrentDictionary>)serviceValue;
// 获取所有已经注册的服务
var allService = serviceProvider.GetAllServiceDescriptors();
List serviceModels = new List();
foreach (var item in allService)
{
serviceModels.Add(new ServiceModel
{
Type = item.Key.ToString(),
ImplementationType = item.Value.ImplementationType?.ToString() ?? "",
Lifetime = item.Value.Lifetime.ToString(),
TypeAssembly = new AssemblyModel
{
FullName = item.Key.Assembly.FullName,
},
ImplementationTypeAssembly = new AssemblyModel
{
FullName = item.Value.ImplementationType?.Assembly?.FullName ?? ""
}
});
}
responseModel.Code = 1;
responseModel.Message = "success";
responseModel.Data = serviceModels;
}
catch (Exception ex)
{
responseModel.Code = -1;
responseModel.Message = "error";
responseModel.Data = ex.ToString();
}
return await Task.FromResult(responseModel);
}
#endregion Actions
public sealed class AssemblyLoadContextsResponseDataModel
{
public AssemblyLoadContextModel Default
{
get; set;
}
public List All
{
get; set;
}
public sealed class AssemblyLoadContextModel
{
public string Name
{
get; set;
}
public string Type
{
get; set;
}
public List Assemblies
{
get; set;
}
}
}
public sealed class AssembliesResponseDataModel
{
}
public sealed class ServiceModel
{
public string Type
{
get; set;
}
public string ImplementationType
{
get; set;
}
public string Lifetime
{
get; set;
}
public AssemblyModel TypeAssembly
{
get; set;
}
public AssemblyModel ImplementationTypeAssembly
{
get; set;
}
}
public sealed class AssemblyModel
{
public string FullName
{
get; set;
}
public List DefinedTypes
{
get; set;
}
}
}