Search code examples
c#dependency-injectionautofacproperty-injection

Property injected value is null in constructor


I'm wiring up Autofac dependency injection within my ASP.NET MVC 5 web application using OWIN middleware (so using startup.cs instead of global.asax), and trying to use property injection to set a public variable within a Controller.

I'm playing around with property injection to have Autofac automatically set the Test property in the LoginController.

public interface ITest
{
    string TestMethod();
}

public class Test : ITest
{
    public string TestMethod()
    {
        return "Hello world!";
    }
}

public class LoginController : Controller
{
    public ITest Test { get; set; }

    public LoginController()
    {
        var aaa = Test.TestMethod();

        // Do other stuff...
    }
}

Here's what my startup.cs looks like. I have been playing around, so some of this code might not be needed (or causing my issue?).

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
        builder.RegisterType<Test>().As<ITest>().SingleInstance();
        builder.Register(c => new Test()).As<ITest>().InstancePerDependency();

        builder.RegisterType<ITest>().PropertiesAutowired();
        builder.RegisterType<LoginController>().PropertiesAutowired();

        builder.RegisterModelBinderProvider();
        builder.RegisterFilterProvider();

        var container = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        app.UseAutofacMiddleware(container);

        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        // Some other stuff...
    }
}

So, the 'Test' public property is always null, and therefore breaks on runtime.

Any ideas what could be my issue? Thanks advance for your help! :)


Solution

  • So, the 'Test' public property is always null, and therefore breaks on runtime.

    It's not always null. It's null in the constructor because Autofac (actually ALL code) cannot set properties until the constructor is finished.

    public class LoginController : Controller
    {
        public ITest Test { get; set; }
    
        public LoginController()
        {
            // Test is null, will always be null here
            var aaa = Test.TestMethod();
        }
    }
    

    A super dummied down version of autofac does something like:

    var controller = new LoginController();
    controller.Test = new Test();
    

    If you need to execute code after the property is set you could do something hacky like the following (but really you should just be using constructor injection):

    public class LoginController : Controller
    {
        private ITest _test;
        public ITest Test 
        { 
          get { return _test; }
          set 
          {
            var initialize = (_test == null);
            _test = value;
            if (initialize)
            {
              Initialize();
            }
          }
        }
    
        public LoginController()
        {
        }
    
        private void Initialize()
        {
          var aaa = Test.TestMethod();
        }
    }
    

    Again the more logical way would be to just do:

    public class LoginController : Controller
    {
        private readonly ITest _test;
    
        public LoginController(ITest test)
        {
            _test = test;
            var aaa = _test.TestMethod();
    
            // Do other stuff...
        }
    }