Значение введенного свойства равно null в конструкторе

Я подключаю внедрение зависимостей Autofac в свое веб-приложение ASP.NET MVC 5 с использованием промежуточного программного обеспечения OWIN (поэтому использую startup.cs вместо global.asax) и пытаюсь использовать внедрение свойств для установки общедоступной переменной в контроллере.

Я играю с внедрением свойств, чтобы Autofac автоматически устанавливал свойство Test в 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...
    }
}

Вот как выглядит мой файл startup.cs. Я играл, поэтому часть этого кода может не понадобиться (или вызвать мою проблему?).

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...
    }
}

Таким образом, общедоступное свойство «Тест» всегда имеет значение null и, следовательно, прерывается во время выполнения.

Любые идеи, что может быть моей проблемой? Заранее спасибо за помощь! :)


person Dan Gilberstadt    schedule 16.02.2017    source источник
comment
Возможный дубликат Как использовать внедрение свойств с AutoFac?   -  person Steve    schedule 17.02.2017
comment
Мне кажется, у вас неправильная регистрация. Контроллеру необходимо применить PropertiesAutowired, а не зависимость.   -  person Steve    schedule 17.02.2017
comment
Вам либо нужно передать свой тестовый объект в конструктор, либо не использовать этот объект в конструкторе. Свойства не могут быть назначены до выполнения конструктора.   -  person trailmax    schedule 17.02.2017
comment
@ Стив, спасибо за это, я попробую.   -  person Dan Gilberstadt    schedule 19.02.2017
comment
@trailmax, да, вы правы, свойства не устанавливаются до тех пор, пока не запустится конструктор.   -  person Dan Gilberstadt    schedule 19.02.2017


Ответы (1)


Таким образом, общедоступное свойство «Тест» всегда имеет значение null и, следовательно, прерывается во время выполнения.

Это не всегда ноль. В конструкторе он нулевой, потому что Autofac (фактически ВЕСЬ код) не может устанавливать свойства, пока конструктор не будет завершен.

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

    public LoginController()
    {
        // Test is null, will always be null here
        var aaa = Test.TestMethod();
    }
}

Упрощенная версия autofac делает что-то вроде:

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

Если вам нужно выполнить код после установки свойства, вы можете сделать что-то хакерское, например следующее (но на самом деле вы должны просто использовать внедрение конструктора):

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();
    }
}

Опять же, более логичным способом было бы просто сделать:

public class LoginController : Controller
{
    private readonly ITest _test;

    public LoginController(ITest test)
    {
        _test = test;
        var aaa = _test.TestMethod();

        // Do other stuff...
    }
}
person Erik Philips    schedule 17.02.2017
comment
Ааа, спасибо Эрик! Не понял, что тест будет установлен ПОСЛЕ завершения конструктора. Я вижу, что это работает сейчас. Думаю, мне пора идти. Спасибо! - person Dan Gilberstadt; 17.02.2017