如何从Unity映射中删除(取消注册)已注册的实例?

bug*_*g0r 34 c# instance ioc-container unity-container registering

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

UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
Run Code Online (Sandbox Code Playgroud)

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

在这里我注册instance为一个实例IMyInterface.

所以在任何地方(使用后一段时间)我想删除此映射.完全删除它.我怎么能这样做?

我试过了:

UnityHelper.DefaultContainer.Teardown(instance)
Run Code Online (Sandbox Code Playgroud)

但是不成功,以下代码仍会返回instance:

UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
Run Code Online (Sandbox Code Playgroud)

Joh*_*zek 28

我有同样的问题,只是删除了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();
}
Run Code Online (Sandbox Code Playgroud)


er-*_*r-v 11

我认为这就是你要找的东西.

var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Run Code Online (Sandbox Code Playgroud)


Bra*_*rad 9

以下是我从统一容器处理取消注册实例的方法

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

public interface IObjectBuilder
{
    void AddInstance<T>(T instance);
    void RemoveInstance<T>(T instance);
}
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是最终实施:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

在自定义生存期管理器上调用removevalue会导致实例未注册


Mus*_*ata 6

这是一个老问题,但有些答案会产生误导,所以我会提供自己的答案.你不能用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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

总结一下,无论你是做什么ClearValue,用另一个IoC或自定义类包装你的寄存器实例,或提供你自己的LifeTimeManager,ResolveAll<T>并且IsRegistered<T>不会按预期运行,并且注册仍然存在.因此,不要尝试它,因为它不会工作,它将导致问题.