7
votes

Est-il possible dans Autofac de résoudre tous les services d'un type, même s'ils étaient enregistrés avec un nom ou une clé?

dans Autofac on peut faire ce qui suit pour obtenir tous les services enregistrés: xxx

Cependant, cela n'inclut pas ceux qui ont été enregistrés comme des services nommés.

La source Autofac, il semble que cela soit car les services sont interrogés pour la résolution basée sur un service TypeDservice ou sur un service à clé.

est là un moyen de résoudre tous les services à un iNeumable, quant à savoir s'ils étaient inscrits avec un nom ou pas?


0 commentaires

3 Réponses :


2
votes

J'ai écrit une méthode qui semble fonctionner; J'apprécierais les commentaires s'il y a une manière intégrée de le faire dans Autofac. Dans l'exemple ci-dessous, le champ _Context est de type 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;
    }


1 commentaires

Plutôt que d'utiliser résolution () et résoldette () ici, vous pouvez envisager d'utiliser la méthode résolvecomonent () . Cela va mieux gérer les cas où plusieurs implémentations existent pour le même service (ou avec la même clé.)



7
votes

La meilleure option ici consiste à enregistrer les éléments à l'aide de la clé et du service "dactylographié" régulier: xxx

Vous pouvez alors résoudre simplement iEnumerable Pour obtenir le résultat que vous avez après, tout en les résolvant par clé (ou nom) est également pris en charge.

Si vous êtes préoccupé par le maintien d'une inscription par défaut particulière pour ibeverage Il suffit d'utiliser présesveEexistingDefault () sur les autres (ou assurez-vous que la valeur par défaut prévue est enregistrée en dernier).

hth!

Nick


3 commentaires

Aide rapide suivie d'une réponse différée de l'OP n'est pas très zen, d'énormes excuses! J'aurais dû mentionner dans ma question que je ne suis pas nécessairement en contrôle de toutes les inscriptions. Cela fait partie d'une abstraction au-dessus de Autofac, dans un cadre utilisé pour construire des sites (Umbraco 5) afin que notre cadre puisse être utilisé dans des solutions tierces qui possèdent une entreprise ou une autre dépendance sur un autre conteneur ou une autre libération d'autofac entièrement sans notre propre code d'enregistrement interne étant spécifique au fournisseur.


Il semble que, avec cette inscription, les composants de ce iEnumerable sont tous diffèrent d'un composant résolu par ce nom context.Resolezkeyed ("Sommeille") .


Mais il peut être résolu en ajoutant .SingleInstance () à votre inscription.



0
votes

Il semblerait que vous puissiez combiner les méthodes comme () code> et nommé () code> méthodes comme indiqué ci-dessous:

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


2 commentaires

Il semble que, avec cet enregistrement, les composants de allInstances sont tous diffèrent des composants résolus par nom conteneur.Resolezkeyed (...) .


Mais si vous fournissez .SingleInstance () à votre inscription, allInstances et résolvoyé Les instances seront égales.