Получить список всех зарегистрированных объектов, реализующих определенный интерфейс

Рассмотрим следующее

builder.Register(c => new A());
builder.Register(c => new B());
builder.Register(c => new C());

B и C равны ISomeInterface.

Теперь я хотел бы получить IEnumerable всех зарегистрированных объектов, которые реализуют ISomeInterface.

Как это сделать в Autofac?

Ответ 1

Только что попробовал, работает и не зависит от жизненного контекста:

Вместо этого перечисляйте типы, используя Activator

var types = con.ComponentRegistry.Registrations
     .Where(r => typeof(ISomeInterface).IsAssignableFrom(r.Activator.LimitType))
     .Select(r => r.Activator.LimitType);

Затем решить:

IEnumerable<ISomeInterface> lst = types.Select(t => con.Resolve(t) as ISomeInterface);

Ответ 2

Если у вас

container.Register(c => new A()).As<ISomeInterface>();
container.Register(c => new B()).As<ISomeInterface>();

Затем, когда вы делаете

var classes = container.Resolve<IEnumerable<ISomeInterface>>();

Вы получите переменную, которая представляет собой список ISomeInterface, содержащий A и B

Ответ 3

Вот как я это сделал.

var l = Container.ComponentRegistry.Registrations
          .SelectMany(x => x.Services)
          .OfType<IServiceWithType>()
          .Where(x => 
                 x.ServiceType.GetInterface(typeof(ISomeInterface).Name) != null)
          .Select(c => (ISomeInterface) c.ServiceType);

Ответ 4

Мне нужно было решить на основе некоторого контекста. Такая небольшая вариация...

 builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(ISomeStrategy)))
   .Where(t => typeof(ISomeStrategy).IsAssignableFrom(t))
   .AsSelf();

 builder.Register<Func<SomeEnum, ISomeStrategy>>(c =>
 {
    var types = c.ComponentRegistry.Registrations
      .Where(r => typeof(ISomeStrategy).IsAssignableFrom(r.Activator.LimitType))
      .Select(r => r.Activator.LimitType);

    ISomeStrategy[] lst = types.Select(t => c.Resolve(t) as ISomeStrategy).ToArray();

    return (someEnum) =>
    {
      return lst.FirstOrDefault(x => x.CanProcess(someEnum));
    };
 });

Тогда для вашего класса используйте стратегию

 public SomeProvider(Func<SomeType, ISomeStrategy> someFactory)
 {
    _someFactory = someFactory;
 }

 public void DoSomething(SomeType someType)
 {
    var strategy = _someFactory(someType);
    strategy.DoIt();
 }