using NetDocsForLLM.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace NetDocsForLLM.Services
{
///
/// Implementación del servicio de análisis de ensamblados basado en Reflection
///
public class ReflectionAnalyzerService : IDocFxService
{
private readonly string _workingDirectory;
public ReflectionAnalyzerService()
{
// Crear un directorio temporal para trabajar
_workingDirectory = Path.Combine(Path.GetTempPath(), "NetDocsForLLM_" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(_workingDirectory);
}
public async Task GenerateMetadataAsync(IEnumerable assemblies)
{
// Crear directorio para metadatos
var metadataPath = Path.Combine(_workingDirectory, "metadata");
Directory.CreateDirectory(metadataPath);
// Para cada ensamblado, generar archivo de metadatos
foreach (var assembly in assemblies)
{
await Task.Run(() => ProcessAssembly(assembly, metadataPath));
}
return metadataPath;
}
private void ProcessAssembly(AssemblyModel assemblyModel, string outputPath)
{
try
{
var assembly = assemblyModel.LoadedAssembly;
if (assembly == null)
throw new ArgumentException("El ensamblado no está cargado", nameof(assemblyModel));
// Cargar comentarios XML si existen
XDocument xmlDoc = null;
if (assemblyModel.HasXmlDocumentation && File.Exists(assemblyModel.XmlDocPath))
{
try
{
xmlDoc = XDocument.Load(assemblyModel.XmlDocPath);
}
catch (Exception)
{
// Si hay error al cargar XML, continuar sin comentarios
}
}
// Procesar todos los tipos exportados
foreach (var type in assembly.GetExportedTypes())
{
try
{
// Generar archivo de metadatos para cada tipo
var typeInfo = new
{
Name = type.Name,
FullName = type.FullName,
Namespace = type.Namespace,
IsClass = type.IsClass,
IsInterface = type.IsInterface,
IsEnum = type.IsEnum,
IsAbstract = type.IsAbstract,
IsSealed = type.IsSealed,
IsPublic = type.IsPublic,
BaseType = type.BaseType?.FullName,
Interfaces = type.GetInterfaces().Select(i => i.FullName).ToArray(),
XmlDocumentation = GetXmlDocumentation(xmlDoc, GetMemberXmlId(type)),
Members = GetMembers(type, xmlDoc)
};
// Guardar en archivo JSON
string typePath = Path.Combine(outputPath, $"{type.FullName.Replace('+', '_')}.json");
File.WriteAllText(typePath, JsonConvert.SerializeObject(typeInfo, Formatting.Indented));
}
catch (Exception ex)
{
// Registrar error para este tipo pero continuar con otros
File.WriteAllText(
Path.Combine(outputPath, $"error_{type.FullName.Replace('+', '_')}.txt"),
$"Error procesando tipo {type.FullName}: {ex.Message}\n{ex.StackTrace}");
}
}
}
catch (Exception ex)
{
// Registrar el error pero continuar con otros ensamblados
File.WriteAllText(
Path.Combine(outputPath, $"error_{Path.GetFileNameWithoutExtension(assemblyModel.FilePath)}.txt"),
$"Error procesando ensamblado: {ex.Message}\n{ex.StackTrace}");
}
}
private object[] GetMembers(Type type, XDocument xmlDoc)
{
var result = new List