c# - tamaño - unity destroy gameobject
Cómo eliminar(anular el registro) instancia registrada de la asignación de Unity (6)
Aquí es cómo manejé las instancias de eliminación de registro de un contenedor de unidad
Necesitaba implementar la funcionalidad Agregar / Eliminar como esta:
public interface IObjectBuilder
{
void AddInstance<T>(T instance);
void RemoveInstance<T>(T instance);
}
Creé un administrador de por vida personalizado para hacer la implementación
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;
}
}
Aquí está la implementación final:
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);
}
invocar removevalue en el administrador de por vida personalizado hace que la instancia no se registre
Me encuentro con un problema que no puedo resolver ahora. Tengo lo siguiente:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
donde UnityHelper.DefaultContainer
es mi ayudante para obtener el contenedor de unidad con la configuración cargada.
aquí IMyInterface
instance
como una instancia de IMyInterface
.
Entonces, en cualquier lugar (algún tiempo después del uso), quiero eliminar esta asignación. Eliminarlo en absoluto. ¿Cómo puedo hacerlo?
Yo he tratado:
UnityHelper.DefaultContainer.Teardown(instance)
pero no fue exitoso y el siguiente código devuelve la instance
todos modos:
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
Creo que eso es lo que estás buscando.
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Esta es una pregunta antigua, pero algunas respuestas son engañosas, por lo que proporcionaré la mía. No puedes hacer eso con Unity. El final de la historia. Llamar a RemoveValue
en los administradores de registros de por vida no logra anular el registro ( más información sobre los administradores de por vida ), y ese método no tiene la intención de anular el registro de nada. Entonces, el comportamiento final es inesperado y no es conveniente. Por supuesto, RemoveValue
tiene aún menos sentido si registra una implementación o un método de fábrica, aunque la pregunta es sobre anular el registro de instancias. Considere la siguiente pieza de código
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();
}
}
Si lo depura, verá que después de la llamada a ClearValue
, el contenedor aún dice que está registrado, pero si intenta resolver esa instancia lanzará una excepción. Lo que es aún peor, las llamadas a ResolveAll<T>
también fallarán.
En ClearValue
, no importa si lo hace ClearValue
, envuelve su instancia de registro con otro IoC o una clase personalizada, o proporciona su propio LifeTimeManager, ResolveAll<T>
e IsRegistered<T>
no se comportarán como se esperaba, y el registro se realizará todavía estar allí. Así que no lo intentes porque no funcionará y causará problemas en el futuro.
Tenía un requisito similar por el cual quería almacenar temporalmente los objetos en el contenedor de la unidad y descubrí que esto no era posible (o al menos era posible). Si su objetivo es tener un lugar de almacenamiento temporal fácilmente disponible para la unidad, cree un servicio de almacenamiento temporal.
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;
}
}
Registre su servicio con Unity. Luego, cuando desee almacenar un objeto, llame al Método de depósito y cuando desee eliminar el objeto, llame al método Retirar. Una explicación más completa se puede encontrar aquí
Tengo el mismo desafío y después de experimentarlo lo resolví utilizando el ContainerControlledLifetimeManager estándar y llamando a RemoveValue cuando quiero eliminar la instancia del contenedor. Tenga en cuenta que si no está utilizando interfaces y su objeto tiene un constructor que el contenedor puede encontrar y usar, recreará la instancia una vez que la haya destruido con 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; }
}
}
Tuve el mismo problema y simplemente eliminé los registros del ContainerControlledLifetimeManager
de mi Container
:
foreach (var registration in container.Registrations
.Where(p => p.RegisteredType == typeof(object)
&& p.LifetimeManagerType == typeof(ContainerControlledLifetimeManager)))
{
registration.LifetimeManager.RemoveValue();
}