37

我遇到了一个我现在无法解决的问题。我有以下内容:

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

我的助手在哪里UnityHelper.DefaultContainer获取带有加载配置的统一容器。

在这里,我注册instanceIMyInterface.

所以在任何地方(使用后的一段时间)我都想删除这个映射。完全删除它。我该怎么做?

我努力了:

UnityHelper.DefaultContainer.Teardown(instance)

但是不成功,并且以下代码仍然返回instance

UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
4

6 回答 6

29

我有同样的问题,只是ContainerControlledLifetimeManager从我的Container

foreach (var registration in container.Registrations
    .Where(p => p.RegisteredType == typeof(object)
                && p.Name == name
                && p.LifetimeManager.Type == typeof(ContainerControlledLifetimeManager)))
{
    registration.LifetimeManager.RemoveValue();
}
于 2013-06-21T13:12:15.080 回答
11

我认为这就是你要找的。

var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
于 2010-04-24T20:05:02.943 回答
11

这是一个老问题,但有些答案具有误导性,因此我将提供自己的答案。Unity 无法做到这一点。故事的结局。调用RemoveValue注册生命周期管理器不会实现注销(有关生命周期管理器的更多信息),并且该方法不打算注销任何东西。所以最终的行为是出乎意料的,也不方便。当然,RemoveValue如果您注册实现或工厂方法,则更没有意义,尽管问题是关于取消注册实例。考虑下一段代码

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

如果你调试它,你会看到在调用 之后ClearValue,容器仍然说它已注册,但如果你尝试解析该实例,它会抛出异常。更糟糕的是,调用ResolveAll<T>也会失败。

总而言之,无论您是否这样做ClearValue,用另一个 IoC 或自定义类包裹您的注册实例,或者提供您自己的 LifeTimeManager,ResolveAll<T>并且IsRegistered<T>不会按预期运行,并且注册仍然存在。所以不要尝试它,因为它不起作用,并且会在未来引起问题。

于 2017-03-30T19:36:31.160 回答
8

这是我从统一容器处理注销实例的方式

我需要实现这样的添加/删除功能:

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

我创建了一个自定义生命周期管理器来执行实现

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

这是最终的实现:

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

在自定义生命周期管理器上调用 removevalue 会导致实例被取消注册

于 2011-03-08T19:28:49.987 回答
2

我有同样的挑战,经过试验,我通过使用标准 ContainerControlledLifetimeManager 解决了它,并在我想删除容器实例时调用 RemoveValue。请注意,如果您不使用接口并且您的对象具有容器可以找到并使用的构造函数,它将在您使用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; }
    }
}
于 2012-11-13T13:40:54.450 回答
1

我有一个类似的要求,我想将对象临时存储在统一容器中,但发现这是不可能的(或者至少很容易做到)。如果您的目标是有一个易于统一使用的临时存储位置,那么创建一个临时存储服务。

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

向 Unity 注册您的服务。然后,当您希望存储对象时调用存款方法,当您希望删除对象时调用提款方法。更完整的解释可以在这里找到

于 2010-04-30T22:40:45.003 回答