Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use autofac to resolve a single instance of a (non-Modal) form until that form is disposed?

I am writing a system tray utility and from the menu there are several different forms that you can open for the application. I am using autofac to resolve the creation of these forms when necessary giving my main form Func and Func dependencies.

If the user selects an option that activates the form, if it is already shown it should receive focus, otherwise autofac should create a new form.

I don't really want these forms sitting in memory while they aren't in use, so I am currently letting the form Dispose of itself when the user closes it.

What I need to know is how I can notify autofac that the form has been disposed so that:

  1. It no longer contains a reference to the disposed form (and can thus be garbage collected)
  2. When I next request autofac for an instance of the form it creates a new one.

I've been reading the Autofac wiki and I'm guessing that I just need to set the LifetimeScope properly.

like image 841
Rhys Parry Avatar asked Oct 12 '22 00:10

Rhys Parry


1 Answers

What you're doing is a little outside the norm so I don't think Autofac's standard lifetimescopes apply. I have a similar scenario where I have a type where I want a single instance of a type that is replaceable/reloadable. What I did was register a wrapper class. Adapting to a Winform, would look something like...

public class SingletonFormProvider<TForm> : IDisposable
    where TForm: Form
{
    private TForm _currentInstance;
    private Func<TForm> _createForm;

    public SingletonFormProvider(Func<TForm> createForm)
    {
        _createForm = createForm;
    }

    public TForm CurrentInstance
    {
         get
         {
              if (_currentInstance == null)
                  _currentInstance = _createForm();

              // TODO here: wire into _currentInstance close event
              // to null _currentInstance field

              return _currentInstance;
         }
    }

    public void Close()
    {
        if (_currentInstance == null) return;

        _currentInstance.Dispose();
        _currentInstance = null;
    }

    public void Dispose()
    {
        Close();
    }
}

Then you can register

builder
    .Register(c => new SingletonFormProvider<YourForm>(() => new YourForm())
    .AsSelf()
    .SingleInstance();
builder
    .Register(c => c.Resolve<SingletonFormProvider<YourForm>>().CurrentInstance)
    .AsSelf();
like image 98
Jim Bolla Avatar answered Oct 31 '22 20:10

Jim Bolla