Подтвердить что ты не робот

Разрешение общего интерфейса с Autofac

Учитывая следующий код, как мне разрешить право SomeInstance в 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

Я хочу выбрать SomeInstance1 или 2 в зависимости от типа обобщенного в подклассах.

Итак, например, у меня есть набор подклассов (SubClass1, 2....), и, итерации по ним, я хочу выбрать правильный класс SomeInstance.

4b9b3361

Ответ 1

Autofac поддерживает открытые дженерики. Вы можете использовать следующий код, если тип обобщения известен во время компиляции:

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);

Если параметр типа неизвестен до времени выполнения (что, скорее всего, является вашим случаем, если вы хотите выполнить итерацию по набору типов), вы можете создать свой тип с помощью MakeGenericType:

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

Ответ 2

Коррекция. Вы не можете вызвать MakeGenericType из Контейнера. Я решил проблему создания Generics, используя "TYPE" в качестве параметра вызова Resolve. Строитель зарегистрирован.

        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);
            }
        });

Затем разрешение происходит так: передача TypedParameter в Resolve. В этом случае у меня есть список элементов (IItem), которые разрешены, что я хочу создать репозиторий для всех элементов этого типа.

        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);
        }

Спасибо за ваш пост, это помогло, и я надеюсь, что это обновление поможет.