2010-04-24 16 views
30

Je rencontre un problème que je ne peux pas résoudre maintenant. Je donne les résultats suivants:Comment supprimer (désenregistrer) une instance enregistrée du mappage Unity

UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance); 

UnityHelper.DefaultContainer est mon aide pour obtenir conteneur d'unité avec la configuration chargée. Ici, j'ai enregistré instance comme une instance de IMyInterface.

Donc n'importe où (quelque temps après l'utilisation) Je veux supprimer ce mappage. Retirez-le du tout. Comment je peux le faire?

J'ai essayé:

UnityHelper.DefaultContainer.Teardown(instance) 

mais est a échoué et le code suivant retourne instance de toute façon:

UnityHelper.DefaultContainer.ResolveAll<IMyInterface>() 
+0

Intéressant. Pourquoi en avez-vous besoin d'ailleurs? –

+0

J'utilise des instances simulées dans les tests et je veux effacer l'environnement pour le prochain test. Actuellement, les instances du test précédent se trouvent dans le conteneur et apparaissent lorsque j'appelle ResolveAll (). – bug0r

+0

Dans le scénario Commmon, le développeur peut modifier l'implémentation à la volée. – bug0r

Répondre

11

Je pense que est ce que vous recherchez.

var lifetimeManager = new TransientLifetimeManager(); 
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager); 
lifetimeManager.RemoveValue(); 
+0

va essayer de cette façon – bug0r

+0

alors, ça a marché? –

+0

Non, ce n'est pas le cas. L'exception augmente lors de la deuxième exécution de résolution. – bug0r

2

J'ai eu une exigence similaire par laquelle je voulais stocker temporairement des objets dans le conteneur d'unité et trouvé cela n'a pas été possible (ou au moins facilement possible). Si votre objectif est d'avoir un lieu de stockage temporaire facilement disponible pour unity, créez un service de stockage temporaire.

public class TemporaryStorageService : ITemporaryStorageService 
{ 
    public void Deposit<T>(Object o, string key) 
    { 
     System.Windows.Application.Current.Properties[key] = o; 
    } 

    public T Withdraw<T>(string key) 
    { T o = (T)System.Windows.Application.Current.Properties[key]; 
     System.Windows.Application.Current.Properties.Remove(key); 
     return o; 
    } 
} 

Enregistrez votre service avec Unity. Ensuite, lorsque vous souhaitez stocker un objet, vous appelez la méthode de dépôt et lorsque vous souhaitez retirer l'objet, vous appelez la méthode de retrait. Une explication plus complète peut être found here

+0

lien est mort ou pointant au mauvais endroit – quetzalcoatl

10

Voici comment je me suis occupé des cas annulation de l'enregistrement d'un conteneur d'unité

je avais besoin de mettre en œuvre Ajout/Suppression de fonctionnalités comme ceci:

public interface IObjectBuilder 
{ 
    void AddInstance<T>(T instance); 
    void RemoveInstance<T>(T instance); 
} 

J'ai créé un gestionnaire de vie personnalisé pour faire la mise en œuvre

public class ExplicitLifetimeManager : 
    LifetimeManager 
{ 
    object Value; 

    public override object GetValue() 
    { 
     return Value; 
    } 

    public override void SetValue(object newValue) 
    { 
     Value = newValue; 
    } 

    public override void RemoveValue() 
    { 
     Value = null; 
    } 
} 

Voici l'implémentation finale:

Dictionary<object, ExplicitLifetimeManager> Instances = new Dictionary<object, ExplicitLifetimeManager>(); 

    public void AddInstance<T>(T instance) 
    { 
     ExplicitLifetimeManager e = new ExplicitLifetimeManager(); 
     Instances[instance] = e; 
     Container.RegisterInstance(instance, e); 
    } 

    public void RemoveInstance<T>(T instance) 
    { 
     Instances[instance].RemoveValue(); 
     Instances.Remove(instance); 
    } 

appelant removeValue sur le gestionnaire de vie personnalisé provoque l'instance d'être non enregistré

4

J'ai le même défi et après l'expérimentation je l'ai résolu en utilisant la norme ContainerControlledLifetimeManager et appelant removeValue quand je veux retirer le récipient exemple. Notez que si vous n'utilisez pas d'interfaces et que votre objet a un constructeur que le conteneur peut trouver et utiliser, il recréera l'instance après l'avoir détruite avec lifeManager.RemoveValue().

[TestClass] 
public class UnityContainerTest 
{ 
    [TestMethod] 
    public void RemoveFromContainer() 
    { 
     UnityContainer container = new UnityContainer(); 
     MyUnityMember member = new MyUnityMember(5); 

     LifetimeManager lifetimeManager = new ContainerControlledLifetimeManager(); 
     container.RegisterInstance(member, lifetimeManager); 

     var resolved = container.Resolve<MyUnityMember>(); 
     Assert.IsNotNull(resolved); 

     lifetimeManager.RemoveValue(); 

     try 
     { 
      resolved = container.Resolve<MyUnityMember>(); 
      Assert.Fail(resolved + " is still in the container"); 
     } 
     catch (ResolutionFailedException) 
     { 
     } 
    } 

    public class MyUnityMember 
    { 
     public MyUnityMember(int x) 
     { 
      I = x; 
     } 

     public int I { get; private set; } 
    } 
} 
+0

Merci pour l'indice à ce sujet ré-instancier des classes concrètes - que l'on m'a fait trébucher! – Steztric

23

J'ai eu le même problème et juste enlevé les enregistrements de la ContainerControlledLifetimeManager de mon Container:

foreach (var registration in container.Registrations 
    .Where(p => p.RegisteredType == typeof(object) 
       && p.LifetimeManagerType == typeof(ContainerControlledLifetimeManager))) 
{ 
    registration.LifetimeManager.RemoveValue(); 
} 
3

C'est une vieille question, mais certaines réponses sont trompeuses, donc je vais donner mon propre. Vous ne pouvez pas faire cela avec Unity. Fin de l'histoire. En appelant RemoveValue sur les enregistrements, les gestionnaires de durée de vie n'obtiennent pas l'annulation de l'enregistrement (more information about lifetime managers), et cette méthode n'est pas destinée à annuler l'inscription. Donc, le comportement final est inattendu et pas pratique. Bien sûr, RemoveValue a encore moins de sens si vous enregistrez une implémentation ou une méthode d'usine, bien que la question concerne les instances de désinscription. Considérons le prochain morceau de code

public interface SomeInterface 
    { 
     int Foo { get; set; } 
    } 

    public class SomeImplementation: SomeInterface 
    { 
     public int Foo { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     UnityContainer iocContainer = new UnityContainer(); 
     string registerName = "instance"; 
     //before any registration 
     Resolve<SomeInterface>(iocContainer, registerName); 

     iocContainer.RegisterInstance<SomeInterface>(registerName, new SomeImplementation()); 

     //after registration 
     Resolve<SomeInterface>(iocContainer, registerName); 

     ClearValue<SomeInterface>(iocContainer, registerName); 

     //after clear value 
     Resolve<SomeInterface>(iocContainer, registerName); 


    } 

    private static void Resolve<T>(UnityContainer iocContainer,string name) 
    { 
     if (iocContainer.IsRegistered<T>(name)) 
      iocContainer.Resolve<T>(name); 

     iocContainer.ResolveAll<T>(); 
    } 
    private static void ClearValue<T>(UnityContainer iocContainer, string name) 
    { 
     foreach (var registration in iocContainer.Registrations.Where(p => p.RegisteredType == typeof(T) 
      && p.Name==name)) 
     { 
      registration.LifetimeManager.RemoveValue(); 
     } 
    } 

Si vous le débogage, vous verrez que, après l'appel à ClearValue, le conteneur dit encore il est enregistré, mais si vous essayez de résoudre ce cas, il lancera une exception . Ce qui est encore pire, les appels à ResolveAll<T> échoueront aussi.

En somme, peu importe si vous faites ClearValue, enrouler autour de votre instance de registre avec un autre IoC ou une classe personnalisée, ou fournir votre propre LifeTimeManager, ResolveAll<T> et IsRegistered<T> se comportent ne le ferai pas comme prévu, et l'enregistrement sera toujours Là. Donc, ne l'essayez pas parce que ça ne marchera pas et cela causera des problèmes sur la route.