Pregunta

Dado el siguiente código, ¿cómo puedo solucionar el SomeInstance justo 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 en función del tipo de la genérica sobre las subclases.

Así, por ejemplo, tengo una colección de clases (sub SubClass1, 2 ....) y al iterar sobre ellos Quiero elegir la clase SomeInstance derecha.

¿Fue útil?

Solución

Autofac apoya genéricos abiertos. Se puede utilizar el siguiente código si el tipo de medicamentos genéricos se conoce en tiempo de 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 el parámetro de tipo no se conoce hasta tiempo de ejecución (que es probable que su caso si desea recorrer colección de tipos), entonces usted puede construir su tipo usando MakeGenericType:

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

Otros consejos

Corrección. No se puede llamar MakeGenericType del contenedor. He resuelto el problema de crear instancias de los genéricos utilizando el 'tipo' como 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);
            }
        });

A continuación, la solución pasa así, pasar un TypedParameter a la Resolve. En este caso, tengo una lista de elementos (iItem) que se resuelven que yo 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 puesto que ayudó y espero que esta actualización ayuda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top