我遇到了一个我现在无法解决的问题。 我有以下内容:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
其中UnityHelper.DefaultContainer
是我的帮助器,用于获取带有加载配置的统一容器。
此处我将instance
注册为IMyInterface
的实例。
所以在任何地方(使用后一段时间)我想删除此映射。完全删除它。我怎么能这样做?
我试过了:
UnityHelper.DefaultContainer.Teardown(instance)
但是不成功,以下代码仍然返回instance
:
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
答案 0 :(得分:27)
我遇到了同样的问题,只是从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();
}
答案 1 :(得分:11)
我认为这就是你要找的东西。
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
答案 2 :(得分:9)
以下是我如何处理来自统一容器的取消注册实例
我需要实现这样的添加/删除功能:
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会导致实例未注册
答案 3 :(得分:6)
这是一个老问题,但有些答案会产生误导,所以我会提供自己的答案。
你不能用Unity做到这一点。故事的结局。
在注册生命周期管理器上调用RemoveValue
无法实现取消注册(more information about lifetime managers),并且该方法不用于取消注册任何内容。所以最后的行为是意外的,不方便。当然,如果您注册实现或工厂方法,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>
won' t表现如预期,注册仍然存在。因此,不要尝试它,因为它不会起作用,它将导致问题。
答案 4 :(得分:3)
我遇到了同样的挑战,经过实验后,我通过使用标准的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; }
}
}
答案 5 :(得分: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注册您的服务。然后,当您希望存储一个对象时,可以调用存款方法,当您想要删除该对象时,可以调用Withdraw方法。 更全面的解释可以是found here