Search code examples
c#inversion-of-controlautofac

Autofac - Singleton interface resolved as transient


I'm building a WPF application and using Autofac as an IoC container. The scenario is kind of hard to describe but I'll try to give the relevant piece of code below:

My app bootstrapper contains the following code to register the viewmodels in my app:

builder.RegisterAssemblyTypes(assemblySource)
       .Where(type => type.Name.EndsWith("ViewModel"))
       .Where(type => !string.IsNullOrWhiteSpace(type.Namespace) && type.Namespace.Contains("ViewModels"))
       .AssignableTo<INotifyPropertyChanged>()
       .AsSelf()
       .InstancePerDependency();

(note the InstancePerDependency() call, which I have to make, because I display many instances of a view)

Then I have the following code to register implementers of an open generic:

builder.RegisterAssemblyTypes(assemblySource)
       .AsClosedTypesOf(typeof(INotificationHandler<>))
       .AsSelf()
       .SingleInstance();

To avoid passing the container into my event dispatcher, I'm passing it instead a delegate as follows:

builder.Register<ServiceFactory>(ctx => { return t => Container.Resolve(t ); });

And the last bit of code is causing me a problem: It's causing the ViewModels that implement the INotificationHandler interface to have instances created on every call, while I need only once instance to be resolved, and the ViewModels implement this generic interface will have only one instance created throughout the application.

Question is: How can I make Autofac resolve single instances of the ViewModels that Implement the INotificationHandler<T> interface, while keeping the other ViewModels to be created PerDependency ?

Thanks.


Solution

  • You need to exclude ViewModels that implements INotificationHandler<> in your first registration. So change your first registration to:

    builder.RegisterAssemblyTypes(Assembly.GetEntryAssembly())
                .Where(type => type.Name.EndsWith("ViewModel"))
                .Where(type => !string.IsNullOrWhiteSpace(type.Namespace) && type.Namespace.Contains("ViewModels"))
                .Where(type => !type.IsAssignableFrom(typeof(INotificationHandler<>)))
                .AssignableTo<INotifyPropertyChanged>()
                .AsSelf()
                .InstancePerDependency();