c# documentation - Resolución de interfaz genérica con Autofac




github xamarin (3)

Dado el siguiente código, ¿cómo resuelvo la SomeInstance correcta en autofac?

public class BaseClass {}

public class SubClass1 : BaseClass {}

public class SubClass2 : BaseClass {}

public interface IGenericInterface<T> where T : BaseClass {}

public class SomeInstance1<T> : IGenericInterface<T> where T : SubClass1

public class SomeInstance2<T> : IGenericInterface<T> where T : SubClass2

Quiero elegir SomeInstance1 o 2 según el tipo de genérico en las subclases.

Así, por ejemplo, tengo una colección de subclases (SubClase1, 2 ...) y mientras estoy iterando sobre ellas quiero elegir la clase SomeInstance correcta.


Answers

Corrección. No puede llamar a MakeGenericType desde el contenedor. Resolví el problema de instanciar Genéricos usando el 'TIPO' como el parámetro en la llamada Resolver. El constructor está registrado.

        builder.RegisterGeneric(typeof (FakeRepository<>)).As(typeof (IRepository<>)).OnActivating(e =>
        {
            var typeToLookup = e.Parameters.FirstOrDefault() as TypedParameter;
            if (typeToLookup != null)
            {
                var respositoryType = typeof (FakeRepository<>);
                Type[] typeArgs = {typeToLookup.Value.GetType()};
                var genericType = respositoryType.MakeGenericType(typeArgs);
                var genericRepository = Activator.CreateInstance(genericType);
                e.ReplaceInstance(genericRepository);
            }
        });

Luego, la resolución sucede así, pasando un parámetro TypedParameter a la resolución. En este caso, tengo una lista de elementos (IItem) que están resueltos y quiero crear un repositorio para todos los elementos de ese tipo.

        var items = container.Resolve<IEnumerable<IItem<string>>>();
        foreach (var item in items)
        {
            var repository = container.Resolve(typeof (IRepository<DataItemBase>), new TypedParameter(item.GetType(), item));
            Assert.IsNotNull(repository);
        }

Gracias por su publicación, me ayudó y espero que esta actualización ayude.


Autofac soporta genéricos abiertos. Puede utilizar el siguiente código si se conoce el tipo de genéricos en el momento de la compilación:

var builder = new ContainerBuilder();

builder.RegisterGeneric(typeof(SomeInstance1<>))
  .As(typeof(IGenericInterface<>));              

var container = builder.Build();

var instance1 = container.Resolve<IGenericInterface<SubClass1>>();

Assert.IsInstanceOfType(typeof(SomeInstance1<SubClass1>), instance1);

Si no se conoce el tipo de parámetro hasta el tiempo de ejecución (que es probable que sea su caso si desea recorrer una colección de tipos), puede generar su tipo utilizando MakeGenericType:

        var typeInRuntime = typeof (SubClass1);
        var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime));

No repetiré las cosas habituales sobre el uso o la liberación de recursos no administrados, todo eso se ha cubierto. Pero me gustaría señalar lo que parece un error común.
Dado el siguiente código

Public Class LargeStuff
  Implements IDisposable
  Private _Large as string()

  'Some strange code that means _Large now contains several million long strings.

  Public Sub Dispose() Implements IDisposable.Dispose
    _Large=Nothing
  End Sub

Me doy cuenta de que la implementación de Desechables no sigue las pautas actuales, pero espero que todos tengan una idea.
Ahora, cuando se llama Dispose, ¿cuánta memoria se libera?

Respuesta: Ninguna.
Al llamar a Dispose puede liberar recursos no administrados, NO PUEDE reclamar la memoria administrada, solo el GC puede hacer eso. Eso no quiere decir que lo anterior no sea una buena idea, seguir el patrón anterior es, de hecho, una buena idea. Una vez que se ha ejecutado Dispose, no hay nada que impida que el GC vuelva a reclamar la memoria que estaba utilizando _Large, incluso aunque la instancia de LargeStuff aún pueda estar dentro del alcance. Las cadenas en _Large también pueden estar en gen 0, pero la instancia de LargeStuff podría ser gen 2, así que nuevamente, la memoria se volverá a reclamar antes.
Sin embargo, no tiene sentido agregar un finalizador para llamar al método Dispose que se muestra arriba. Eso solo retrasará la recuperación de la memoria para permitir que se ejecute el finalizador.





c# autofac