Возможно ли в Autofac разрешить все службы для типа, даже если они были зарегистрированы с именем или ключом? - PullRequest
6 голосов
/ 10 февраля 2011

В Autofac для получения всех зарегистрированных услуг можно сделать следующее:

IEnumerable<MyClass> all = Context.Resolve<IEnumerable<MyClass>>()

Однако это не относится к тем из них, которые были зарегистрированы как именованные службы.

Глядя на источник Autofac, кажется, что это связано с тем, что службы запрашиваются для разрешения на основе TypedService или KeyedService.

Есть ли способ разрешить все службы в IEnumerable, независимо от того, были ли они зарегистрированы с именем или нет?

Ответы [ 3 ]

7 голосов
/ 13 февраля 2011

Лучший вариант здесь - зарегистрировать элементы, используя как ключ, так и обычную «типизированную» услугу:

builder.Register<CupOfT>()
    .As<IBeverage>()
    .Keyed<IBeverage>("someKey");

Затем вы можете просто разрешить IEnumerable<IBeverage>, чтобы получить результат, к которому вы стремитесь, при этом также поддерживается разрешение по ключу (или имени).

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

НТН!

Ник

1 голос
/ 10 февраля 2011

Я написал метод, который, кажется, работает;Буду признателен за обратную связь, если в Autofac есть встроенный способ сделать это.В приведенном ниже примере поле _context имеет тип IComponentContext.

    public IEnumerable<T> ResolveAll<T>()
    {
        // We're going to find each service which was registered
        // with a key, and for those which match the type T we'll store the key
        // and later supplement the default output with individual resolve calls to those
        // keyed services
        var allKeys = new List<object>();
        foreach (var componentRegistration in _context.ComponentRegistry.Registrations)
        {
            // Get the services which match the KeyedService type
            var typedServices = componentRegistration.Services.Where(x => x is KeyedService).Cast<KeyedService>();
            // Add the key to our list so long as the registration is for the correct type T
            allKeys.AddRange(typedServices.Where(y => y.ServiceType == typeof (T)).Select(x => x.ServiceKey));
        }

        // Get the default resolution output which resolves all un-keyed services
        var allUnKeyedServices = new List<T>(_context.Resolve<IEnumerable<T>>());
        // Add the ones which were registered with a key
        allUnKeyedServices.AddRange(allKeys.Select(key => _context.ResolveKeyed<T>(key)));

        // Return the total resultset
        return allUnKeyedServices;
    }
0 голосов
/ 16 октября 2012

Может показаться, что вы можете комбинировать методы As<T>() и Named<T>(), как показано ниже:

    [TestMethod]
    public void ResolveTests()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<ClassA1>().As<IClassA>().Named<IClassA>("1");
        builder.RegisterType<ClassA2>().As<IClassA>().Named<IClassA>("2");
        builder.RegisterType<ClassA3>().As<IClassA>().Named<IClassA>("3");
        var container = builder.Build();

        var allInstances = container.Resolve<IEnumerable<IClassA>>();
        allInstances.Count().Should().Be(3);

        container.ResolveNamed<IClassA>("1").Should().BeAssignableTo<ClassA1>();
        container.ResolveNamed<IClassA>("2").Should().BeAssignableTo<ClassA2>();
        container.ResolveNamed<IClassA>("3").Should().BeAssignableTo<ClassA3>();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...