I am facing problem with disposing unnecessary objects from DI container. I use Prism for Xamarin.Forms with Unity container.
Application gets configuration from some database, creates some services using this configuration and registers this services in container using ContainerControlledLifetimeManager. This services are used while resolving views and viewmodels. When configuration changes application retrieves again changed configuration and now problem comes: how can I remove previous registrations and register new services? If I simply re-register service then previous service is not GC-ed until disposing container.
I cannot dispose container, because it is created and managed by Prism (can I?).
I cannot use child container because Prism will not resolve views and viewmodels using child container (can I?)
Should I use different DI? Does Autofac or other DI support such approach?
EDIT:
I just have tested disposing of re-registered objects in Unity. It came out that re-registering using:
Container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager())
really releases previously registered objects. But I have also registrations using just type:
Container.RegisterType<Foo>(new ContainerControlledLifetimeManager())
or using instance:
Container.RegisterInstance(new Foo())
and these objects are not released when re-registering.
So now the only solution is to reconstruct the Unity container? Or give a try to other ioc container?
Thanks for help to Dan S. and R. Richards.
Recreating Prism container caused problems in navigation. Maybe it is possible to fix it but I do not know how.
Using different IOC container would require too much time to learn it.
I ended up with custom lifetime manager (the solution provided in R. Richards link):
class CustomLifetimeManager : LifetimeManager
{
private object _Value;
public override object GetValue()
{
return _Value;
}
public override void RemoveValue()
{
_Value = null;
}
public override void SetValue(object newValue)
{
_Value = newValue;
}
}
Above lifetime manager allows to remove registrations:
public static class UnityContainerExtension
{
/// <summary>
/// Removes registrations that were registred using <see cref="CustomLifetimeManager"/>
/// </summary>
/// <param name="container"></param>
public static void RemoveCustomLifetimeRegistrations(this IUnityContainer container)
{
var registrations = container.Registrations.Where(r => r.LifetimeManagerType == typeof(CustomLifetimeManager));
foreach(var r in registrations)
{
r.LifetimeManager.RemoveValue();
}
}
}