E
Well, in the end a lot easier than I expected. I was using "Assembly.Load" as I had read that when the bookstore was in the same "bin" folder that the assembly was sufficient, but it seems that for ".Net Core" no, and therefore when I used "Assembly.LoadFrom" is when I got it.It should be noted that I had recommended the use of the NuGet package "McMaster.NETCore.Plugins", and that it actually works, but seeing that it can be used directly with "Assembly" seemed better not to depend on third-party libraries.I detail the process.The first thing is to create a configuration file (JSON) with the dependencies in the business project. It is specified the interface to implement (which presupposes that it is in the same bookstore that invokes it, for example I think it is more than enough), the route of the dll library that will implement it, the class that implements it, and the type of registry (Singleton, Transient, Scoped):[
{
"ContratoEspacioNombres": "PoCInyeccionDesacoplada.Dominio.Contratos.IDireccionesRepository",
"ImplementadorRutaEnsamblado": "PoCInyeccionDesacoplada.InfraestructuraDatos.dll",
"ImplementadorEspacioNombresClase": "PoCInyeccionDesacoplada.InfraestructuraDatos.Repositorios.DireccionesRepository",
"TipoRegistro": "Singleton"
},
{
"ContratoEspacioNombres": "PoCInyeccionDesacoplada.Dominio.Contratos.IInicializacionRepository",
"ImplementadorRutaEnsamblado": "PoCInyeccionDesacoplada.InfraestructuraDatos.dll",
"ImplementadorEspacioNombresClase": "PoCInyeccionDesacoplada.InfraestructuraDatos.Repositorios.InicializacionRepository",
"TipoRegistro": "Transient"
}
]
On the other hand, "IServiceCollection" extends to add the dependencies of the business project, taking the log data of the injection of dependencies of the configuration file explained above:using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using PoCInyeccionDesacoplada.Dominio.Servicios.IoC;
using System.IO;
using System.Reflection;
using Newtonsoft.Json;
namespace PoCInyeccionDesacoplada.Dominio.Servicios
{
/// <summary>
/// Inyección de dependencias del proyecto de Dominio
/// </summary>
public static class DependenciasDominio
{
/// <summary>
/// Método de extensión que realiza la inyección de dependencias del proyecto de Dominio
/// </summary>
/// <param name="services">Collección de servicios para usar la inyección de dependencias</param>
/// <returns>Collección de servicios</returns>
public static IServiceCollection AgregarDependenciasDominio(this IServiceCollection services)
{
var localPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var ficheroConfiguracionDependencias = Path.Combine(localPath, "ConfiguracionDependencias.json");
// Comprueba la existencia del fichero
if (File.Exists(ficheroConfiguracionDependencias))
{
string strConfiguracionDependencias = File.ReadAllText(ficheroConfiguracionDependencias);
// Comprueba que no viene vacío
if (!string.IsNullOrWhiteSpace(strConfiguracionDependencias))
{
var configuracionDependencias = JsonConvert.DeserializeObject<List<ConfiguracionDependencia>>(strConfiguracionDependencias);
// Comprueba que tiene configuraciones
if (configuracionDependencias != null && configuracionDependencias.Any())
{
foreach (var configuracionDependencia in configuracionDependencias)
{
Type tipoContrato = Type.GetType(configuracionDependencia.ContratoEspacioNombres);
// Comprueba que el tipo del contrato está bien definido
if (tipoContrato != null)
{
Type tipoDependencia = null;
// Comprueba si la ruta de la dll es absoluta o relativa
if (File.Exists(configuracionDependencia.ImplementadorRutaEnsamblado))
{
// Ruta absoluta
tipoDependencia = GestorDependencias.ObtenerTipoDependencia(tipoContrato, configuracionDependencia.ImplementadorRutaEnsamblado, configuracionDependencia.ImplementadorEspacioNombresClase);
}
else if (File.Exists(Path.Combine(localPath, configuracionDependencia.ImplementadorRutaEnsamblado)))
{
// Ruta relativa
tipoDependencia = GestorDependencias.ObtenerTipoDependencia(tipoContrato, Path.Combine(localPath, configuracionDependencia.ImplementadorRutaEnsamblado), configuracionDependencia.ImplementadorEspacioNombresClase);
}
// Si encuentra el tipo de dependencia lo añade
if (tipoDependencia != null)
{
// Por defecto es Singleton
switch (configuracionDependencia.TipoRegistro)
{
case OpcionRegistro.Scope:
services.AddScoped(tipoContrato, tipoDependencia);
break;
case OpcionRegistro.Transient:
services.AddTransient(tipoContrato, tipoDependencia);
break;
default:
services.AddSingleton(tipoContrato, tipoDependencia);
break;
}
}
}
}
}
}
}
return services;
}
}
}
And finally it is called the assembly load to solve the type implementer for the interface:using System;
using System.Reflection;
using System.Linq;
namespace PoCInyeccionDesacoplada.Dominio.Servicios.IoC
{
public static class GestorDependencias
{
public static Type ObtenerTipoDependencia(Type tipoContrato, string rutaEnsamblado, string tipoClase)
{
// Se debe hacer con LoadFrom para que cargue las librerías dependientes
Assembly ensamblado = Assembly.LoadFrom(rutaEnsamblado);
return ensamblado.DefinedTypes.FirstOrDefault(t => t.FullName == tipoClase);
}
}
}
Therefore, from the API project the extension method is invoked:// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// Gestión de inyección de dependencias
services.AgregarDependenciasApi()
.AgregarDependenciasDominio();
}
I hope the solution is clear, but I will tell it and edit it to be as legible as possible.Greetings.