Comment faire pour supprimer (unregister) instance enregistrée de Unity mapping

je rencontre un problème que je ne peux pas résoudre maintenant. J'ai le code suivant:

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

UnityHelper.DefaultContainer est mon assistant pour obtenir un conteneur unité avec la configuration chargée.

ici je me suis inscrit instance comme une instance de IMyInterface.

donc n'importe où( un peu de temps après l'utilisation) je veux supprimer ce mapping. Supprimer tout. Comment je peux faire?

j'ai essayé:

UnityHelper.DefaultContainer.Teardown(instance)

mais il n'a pas réussi et le code suivant retourne instance de toute façon:

UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
32
demandé sur BartoszKP 2010-04-24 21:20:49

6 réponses

j'ai eu le même problème et je viens de supprimer les enregistrements du ContainerControlledLifetimeManager à partir de mon Container:

foreach (var registration in container.Registrations
    .Where(p => p.RegisteredType == typeof(object)
                && p.LifetimeManagerType == typeof(ContainerControlledLifetimeManager)))
{
    registration.LifetimeManager.RemoveValue();
}
26
répondu Johannes Wanzek 2015-09-15 14:22:58

je pense que c'est ce que vous cherchez.

var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
11
répondu er-v 2010-04-24 20:05:02

Voici comment j'ai traité les instances de désinsectisation à partir d'un conteneur unité

j'ai besoin de mettre en œuvre Ajouter/Supprimer des 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 l'implémentation

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;
    }
}

Ici est la mise en œuvre 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);
    }

appeler removevalue sur le gestionnaire de durée de vie personnalisé fait que l'instance n'est pas enregistrée

9
répondu Brad 2011-03-08 19:28:49

C'est une vieille question, mais certaines réponses sont trompeuses, donc je vais vous donner mon propre. Tu ne peux pas faire ça avec L'Unité. Fin de l'histoire. Appel de RemoveValue sur les inscriptions les gérants à vie ne parviennent pas à se désinscrire (plus d'informations sur la durée de vie des gestionnaires de), et cette méthode n'a pas pour but de désinscrire quoi que ce soit. Le comportement final est donc inattendu et peu commode. Bien sûr, RemoveValue fait encore moins de sens si vous enregistrez une implémentation ou une méthode d'usine, bien que la question soit de désinscrire Les instances. Envisager 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 qu'après l'appel à ClearValue, le conteneur indique toujours qu'il est enregistré, mais si vous essayez de résoudre cette instance, il lancera une exception. Ce qui est encore pire, les appels à ResolveAll<T> échouera aussi.

Pour résumer, peu importe si vous n' ClearValue, envelopper votre instance de registre avec un autre CIO ou une classe personnalisée, ou fournir votre propre LifeTimeManager,ResolveAll<T> et IsRegistered<T> ne se comportera pas comme prévu, et l'enregistrement sera toujours là. Alors ne l'essayez pas parce que ça ne marchera pas et ça causera des problèmes plus tard.

5
répondu Muscicapa Striata 2017-03-30 19:36:31

j'ai le même défi et après avoir expérimenté je l'ai résolu en utilisant la norme ContainerControlledLifetimeManager et en appelant RemoveValue quand je veux enlever l'instance du conteneur. 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 lifetimeManager.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; }
    }
}
3
répondu Velimir 2012-11-13 13:40:54

j'avais une exigence similaire par laquelle je voulais stocker temporairement des objets dans le conteneur unité et j'ai trouvé que ce n'était pas possible (ou au moins facilement possible). Si votre objectif est d'avoir une place de stockage temporaire facilement disponible à unity, alors créer 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 supprimer l'objet, vous appelez la méthode de retrait. Une meilleure l'explication peut être trouvé ici

1
répondu Allan 2013-05-10 19:37:31