2011-02-23 1 views
11

Quelque chose le long de ces lignes:Est-il possible de supprimer un enregistrement existant du constructeur de conteneur Autofac?

builder.RegisterType<MyType>().As<IType>(); 
builder.RegisterType<MyType2>().As<IType>(); 
builder.DeRegisterType<MyType>().As<IType>() 

var container = builder.Build(); 
var types = container.Resolve<IEnumerable<IType>>(); 
Assert.IsTrue(types.Count == 1); 
Assert.IsTrue(types[0].GetType == typeof(MyType2)); 

Scénario: Je passe par groupe d'assemblées et que je vais, j'inscrire les types mais je veux assurez-vous que je n'ai qu'une mise en œuvre d'un type donné. Je dois le faire avant de créer le conteneur. Je pourrais suivre cela par moi-même mais ce serait bien si Autofac pouvait m'aider un peu.

+0

J'ai une autre raison de vouloir cela: En utilisant RegisterAssemblyTypes, j'obtiens un 'background' par défaut des résolutions 'InstancePerDependencyScope'. Après cela, je veux mettre à jour certains d'entre eux à 'InstancePerLifetimeScope'. Cela fonctionne bien en les réenregistrant jusqu'à ce que je résolve une énumérable d'une certaine interface (par exemple, celle qui est implémentée sur plus d'une classe). Suppression de l'enregistrement «arrière-plan» permettrait cela. –

+2

Pour mon problème particulier, j'ai découvert 'RegisterAssemblyTypes(). Except ()' et d'autres méthodes courantes qui peuvent contrôler la sélection et le traitement des types d'assembly enregistrés. –

Répondre

11

Cela ne peut pas être fait directement en utilisant le ContainerBuilder, sauf si vous recommencez avec un nouveau. Rappelez-vous, après avoir construit un conteneur, vous devriez être capable de construire un nouveau conteneur filtrant les types indésirables et réutilisant les enregistrements du premier conteneur. Comme ceci:

... 
var container = builder.Build(); 

builder = new ContainerBuilder(); 
var components = container.ComponentRegistry.Registrations 
        .Where(cr => cr.Activator.LimitType != typeof(LifetimeScope)) 
        .Where(cr => cr.Activator.LimitType != typeof(MyType)); 
foreach (var c in components) 
{ 
    builder.RegisterComponent(c); 
} 

foreach (var source in c.ComponentRegistry.Sources) 
{ 
    cb.RegisterSource(source); 
} 

container = builder.Build(); 

Ceci n'est guère très élégant mais cela fonctionne. Maintenant, si vous pouviez élaborer sur pourquoi vous voulez faire cela, peut-être qu'il y a un meilleur moyen.

+0

Ajout de la partie Why idea –

+0

. Vous devez également copier la propriété RegistrationSources, mais cela fonctionnera. –

+1

@Nicholas - là, a ajouté la copie des sources. En outre, je ne savais pas quelles implications il avait, mais je me suis retrouvé avec des doublons du composant 'LifetimeScope'. Donc filtrant celui-là aussi. –

1

Peter L. a probablement l'option la plus simple. Pour contourner le problème tout à fait, pouvez-vous modifier la façon dont vous découvrez les composants pour les filtrer avant l'enregistrement? Il semble qu'il doit y avoir une approche qui contourne cela ... Il pourrait également être un défi plus loin sur la piste pour déterminer quels composants conserver ou supprimer.

Une approche plus implicite consiste à remplacer le support IEnumerable pour filtrer les choses que vous ne voulez pas. C'est à dire. Copiez et modifiez ce code pour créer un FilteredCollectionSource qui exclut les composants que vous ne voulez pas.

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService); 

deviendrait:

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService) 
    .Where(reg => /* not a duplicate */); 

Si vous ajoutez votre FilteredCollectionSource au constructeur en utilisant RegisterSource() il devrait se habituer à la place du haut-un.

+0

Malheureusement, je reçois des composants par lots et le nombre de lots est inconnu. Merci pour l'aide –

Questions connexes