Как удалить (отменить регистрацию) зарегистрированный экземпляр из Unity mapping
Я встречаю одну проблему, которую я не могу решить сейчас.
У меня есть следующее:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
где UnityHelper.DefaultContainer
- мой помощник для получения контейнера с загруженной конфигурацией.
здесь я зарегистрировал instance
как экземпляр IMyInterface
.
Итак, где угодно (через некоторое время после использования) я хочу удалить это сопоставление. Удалите его вообще. Как я могу это сделать?
Я пробовал:
UnityHelper.DefaultContainer.Teardown(instance)
но не удалось, и следующий код возвращает instance
в любом случае:
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
Ответы
Ответ 1
У меня была та же проблема, и я просто удалил регистрацию ContainerControlledLifetimeManager
из моего Container
:
foreach (var registration in container.Registrations
.Where(p => p.RegisteredType == typeof(object)
&& p.LifetimeManagerType == typeof(ContainerControlledLifetimeManager)))
{
registration.LifetimeManager.RemoveValue();
}
Ответ 2
Я думаю, это то, что вы ищете.
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Ответ 3
Вот как я обработал незарегистрированные экземпляры из контейнера единства
Мне нужно было реализовать функциональность добавления и удаления следующим образом:
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 в пользовательском менеджере времени жизни заставляет экземпляр незарегистрироваться
Ответ 4
У меня такая же проблема, и после эксперимента я решил ее, используя стандартный 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
У меня было аналогичное требование, когда я хотел временно хранить объекты в контейнере единства и обнаружил, что это невозможно (или, по крайней мере, легко возможно).
Если ваша цель состоит в том, чтобы место для временного хранения было легко доступно для единства, затем создайте службу временного хранения.
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.
Более полное объяснение может быть найдено здесь
Ответ 6
Это старый вопрос, но некоторые ответы вводят в заблуждение, поэтому я буду предоставлять свои собственные.
Вы не можете сделать это с Unity. Конец истории.
Вызов RemoveValue
в менеджерах жизненного цикла регистрации не достигает отмены регистрации (больше информации о пожизненных менеджерах), и этот метод не предназначен для отмены регистрации. Поэтому окончательное поведение неожиданно и не удобно. Разумеется, RemoveValue
делает еще меньше смысла, если вы зарегистрируете реализацию или метод factory, хотя вопрос о незарегистрировании экземпляров.
Рассмотрим следующий фрагмент кода
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>
не будете вести себя так, как ожидалось, и регистрация все равно будет. Поэтому не пытайтесь, потому что это не будет работать, и это вызовет проблемы в будущем.