今は解決できない問題に出会います。私は以下を持っています:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
どこ UnityHelper.DefaultContainer
は、ロードされた構成で単一のコンテナーを取得するための私のヘルパーです。
ここでは、instance
をIMyInterface
のインスタンスとして登録しました。
だからどこでも(使用後しばらくして)このマッピングを削除したいです。完全に削除します。どうすればできますか?
私が試してみました:
UnityHelper.DefaultContainer.Teardown(instance)
しかし、これは失敗し、次のコードはとにかくinstance
を返します。
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
同じ問題が発生し、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();
}
それがあなたが探しているものだと思います。
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Unityコンテナーからの登録解除インスタンスの処理方法は次のとおりです
私はこのような追加/削除機能を実装する必要がありました:
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を呼び出すと、インスタンスが登録解除されます
これは古い質問ですが、いくつかの答えは誤解を招くので、私は自分の質問を提供します。 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>
は動作しません予想通り、登録はまだあります。機能しないので試してはいけません。問題が発生する可能性があります。
同じ問題があり、実験した後、標準の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; }
}
}
同様の要件で、オブジェクトをユニティコンテナーに一時的に格納する必要があり、これは不可能である(または少なくとも簡単に可能である)ことがわかりました。一時保管場所を簡単に利用できるようにすることが目的の場合は、一時保管サービスを作成します。
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にサービスを登録します。次に、オブジェクトを保存する場合はDepositメソッドを呼び出し、オブジェクトを削除する場合はWithdrawメソッドを呼び出します。より詳しい説明は ここにあります