8

I am working on a Windows Phone 8.1 application and I have a base class with public property.

public class ViewModelBase
{
   public ISomeClass MyProp {get;set;}
}

My derived class looks like this

public class MainViewModel : ViewModelBase
{
    private readonly INavigation _navigation;
    public MainViewModel(INavigation navigation)
    {
        _navigation = navigation;
    }
}

In my App.cs I have

 var builder = new ContainerBuilder();
 builder.RegisterType<Navigation>().As<INavigation>();
 builder.RegisterType<SomeClass>().As<ISomeClass>();
 builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());

When MainViewModel is created my INavigation is resolved but MyProp is null. I have tried

builder.Register(c => new ViewModelBase { MyProp = c.Resolve<ISomeClass>() });

builder.Register(c => new ViewModelBase()).OnActivated(e => e.Instance.MyProp = e.Context.Resolve<ISomeClass>());

builder.RegisterType<ViewModelBase>().PropertiesAutowired();

but none of it works!

Solution posted here http://bling.github.io/blog/2009/09/07/member-injection-module-for-autofac/

works but I don't like it :)

I don't want to use constructor injection in this case.

Thank you.

partyelite
  • 822
  • 1
  • 15
  • 26
  • 1
    Can you explain why you "don't want to use constructor injection" when it would clearly solve the problem with barely any effort. – Ian Mercer Nov 07 '14 at 18:54
  • Because I would have to add a dependency in a derived class constructor and pass it to the base constructor. – partyelite Nov 07 '14 at 18:56
  • And you don't like that because? `public MainViewModel(INavigation navigation, ISomeClass someClass) : base (someClass)` This is much easier for people coming after you to understand, they can see everything your class depends on. – Ian Mercer Nov 07 '14 at 18:58
  • 1
    I understand what you are saying and agree with you. I would like to minimize the amount of typing. Maybe it won't be so easy to see on what my class depends on but for now I can live with that. The real question is why doesn't autofac property injection work? – partyelite Nov 07 '14 at 19:08

2 Answers2

18

This will load up all classes that inherit ViewModelBase and inject only the specific properties that you want. A lot of the time, you don't want the other properties on the child class to be injected.

builder.RegisterAssemblyTypes( GetType().Assembly )
    .AssignableTo<ViewModelBase>()
    .OnActivated( args =>
    {
        var viewModel = args.Instance as ViewModelBase;
        if( viewModel != null )
        {
            viewModel.MyProp = args.Context.Resolve<ISomeClass>();
        }
    } );
Josh Close
  • 22,935
  • 13
  • 92
  • 140
  • 3
    This is a great answer if you want to keep property injection limited and not open it to all child classes (when the reason is merely to avoid changing many constructors for example). – Meligy Mar 29 '16 at 04:22
  • 1
    @Meligy Yes, however a simpler way to do this with Controllers is builder.RegisterControllers(typeof(MvcApplication).Assembly).AssignableTo().PropertiesAutowired(); – Justin J Stark Nov 12 '18 at 18:24
7

You must make sure that your viewmodel class, MainViewModel, is registered with property injection. Currently, all you have registered with property injection is ViewModelBase, but think about what you are resolving. You will never resolve ViewModelBase, you're resolving MainViewModels. So that is what needs to be registered in the container.

Try:

builder.RegisterType<MainViewModel>().PropertiesAutowired();
Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131