Equivalentes de las invocaciones de .Register en Simple Injector
Tengo un objeto cuyo constructor requiere un primitivo. Lo registro usando un delegado (por favor, excuse el ejemplo ficticio).
container.Register<account>(() => new Account(1000M), Lifestyle.Singleton);
Registro este tipo Account
como la implementación de una interfaz IAccount
. Al hacerlo utilizando la llamada marcada como B
a continuación, .Verify()
de SimpleInjector muestra el siguiente mensaje de error:
/* B */container.Register<iaccount, account="">(Lifestyle.Singleton);
El constructor del tipo Account contiene el parámetro ‘funds’ de tipo decimal, que no se puede utilizar para la inyección de constructor porque es un tipo de valor. (Parámetro ‘TImplementation’)
El uso de la llamada marcada como A
en su lugar no tiene este problema y funciona como se esperaba:
/* A */container.Register<iaccount>(() => container.GetInstance<account>(), Lifestyle.Singleton);
Parece que asumí incorrectamente que A
y B
serían efectivamente equivalentes. ¿Qué me he perdido? ¿Por qué B
no utiliza el delegado registrado para la creación de la instancia de Account
? Gracias.
A continuación se muestra un archivo en formato LINQPad (.linq):
“`csharp
<query kind="Program">
<nugetreference>SimpleInjector</nugetreference>
<namespace>SimpleInjector</namespace>
</query>
void Main()
{
var containerRegistry = new ContainerRegistry();
Console.WriteLine("Balance = " + containerRegistry.GetInstance<account>().Balance);
}
public class ContainerRegistry
{
private readonly Container container = new Container();
<pre><code>public ContainerRegistry()
{
container.Register<account>(() => new Account(1000M), Lifestyle.Singleton);
/* A */container.Register<iaccount>(() => container.GetInstance<account>(), Lifestyle.Singleton);
/* B */container.Register<iaccount, account="">(Lifestyle.Singleton);
container.Verify();
}
[Obsolete] public TInstanceType GetInstance<tinstancetype>() where TInstanceType : class
=> container.GetInstance<tinstancetype>();
</code></pre>
}
public class Account : IAccount
{
public decimal Balance => funds;
<pre><code>private readonly decimal funds;
public Account(decimal funds)
{
this.funds = funds;
}
</code></pre>
}
public interface IAccount
{
decimal Balance { get; }
}
“`</iaccount,></iaccount,>
davy.ai
El problema al registrar
IAccount
utilizando la llamada marcada comoB
es que SimpleInjector intenta crear una instancia deAccount
directamente, sin utilizar el delegado registrado para crear instancias deAccount
. Esto ocurre porque en la llamadaB
, SimpleInjector está diciéndole al contenedor queAccount
es la implementación deIAccount
, y que debería ser capaz de crear una instancia deAccount
sin más orientación. Sin embargo, comoAccount
requiere un parámetro primitivo en su constructor, SimpleInjector no sabe cómo obtener el valor para este parámetro, y por lo tanto falla.Por otro lado, al utilizar la llamada marcada como
A
, SimpleInjector crea una instancia deIAccount
obteniendo primero una instancia deAccount
utilizando el delegado registrado, y luego realizando un casting aIAccount
. De esta manera, el delegado se utiliza correctamente para obtener el valor necesario del parámetro primitivo para crearAccount
.En resumen, mientras que tanto
A
comoB
registran efectivamenteAccount
como la implementación deIAccount
, soloA
garantiza que el delegado registrado para crear instancias deAccount
se utilice al crear instancias deIAccount
.