Как разрешить внедрение свойств с помощью Autofac?

У меня есть веб-приложение MVC, которое использует Autofac для внедрения сервисов в контроллеры.

Проблема: я пытаюсь внедрить свойство в службу, и мне это не удается (свойство всегда имеет значение null).

Что я ожидаю: я ожидаю, что Autofac правильно инициализирует свойство (не нуль).

Пример:

  • Я пытаюсь внедрить AliasesService как IAliasesService в контроллеры.
  • AliasesService зависит от MailService.
  • MailService является свойством AliasesService.
  • AliasesService правильно создается и передается в MyController.
  • MailService НЕ создан должным образом и установлен в свойство AliasesService.

Контроллер:

public class MyController: Controller
{
    private IAliasesService AliasesService { get; set; }

    public MyController(IAliasesService aliasesService)
    {
        AliasesService = aliasessService;
    }

    public ActionResult Index()
    {
        var model = aliasesService.GetUserRoles();

        return View();
    }
}

Глобальный.asax:

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

builder.RegisterType<MailService>().As<IMailService>();
builder.RegisterType<AliasesService>().As<IAliasesService>().PropertiesAutowired();

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Служба псевдонимов:

public class AliasesService
{
     public IMailService MailService { get; set; }

     public Dictionary<int,string> GetUserRoles()
     {
          MailService.SendMail("method GetUserRoleshas been called");
          return null;
     }
}

Стоит упомянуть:

  • если я попытаюсь сделать инъекцию свойств для контроллеров, это сработает, как и ожидалось.
  • внедрение конструктора работает, но мне нужно внедрение свойства.

Что еще я безуспешно пробовал:

1

builder.RegisterType<MailService>()
       .As<IMailService>();
builder.Register(c => new AliasesService() 
       { 
           MailService = c.Resolve<IMailService>() 
        })
       .As<IAliasesService>();

2

builder.RegisterType<MailService>()
       .As<IMailService>();
builder.RegisterType<AliasesService>()
       .WithProperty("MailService", new MailService())
       .As<IAliasesService>();

Минимальный пример:

using Autofac;

namespace ConsoleApplication1
{
    public interface IBar
    {    
    }

    public class Bar: IBar
    {
        public string Text { get; set; }

        public Bar()
        {
            Text = "Hello world!";
        }
    }

    public interface IFoo
    {
    }

    public class Foo: IFoo
    {
        public IBar Bar { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<Bar>().As<IBar>();
            builder.RegisterType<Foo>().As<IFoo>().PropertiesAutowired();

            var container = builder.Build();

            var foo = container.Resolve<IFoo>();
        }
    }
}

Альтернативное решение:

Для минимального примера Autofac работает, но в контексте контроллеров мне все еще не удалось заставить его работать должным образом, поэтому я отказался от его использования, так как потратил слишком много времени. Сейчас я использую Castle Windsor, и он делает все, что мне нужно, спасибо за поддержку.


comment
Что не работает? Похоже, в вашем коде нет ничего плохого (кроме того, что у вас есть несколько регистраций одной и той же абстракции). Опубликуйте короткий, но полный пример, демонстрирующий проблему. Каков тип свойства MailService? MailService или IMailService ?   -  person Sriram Sakthivel    schedule 14.04.2015
comment
MailService является собственностью DbRespository или AliasesService? (Я думаю, что это ошибка в вашем примере кода). Все испробованные решения должны работать. Не могли бы вы поделиться кодом ваших контроллеров и сервисов? (только конструктор и свойства)   -  person Cyril Durand    schedule 14.04.2015
comment
Заявления сверху - это то, что я пробовал. Я получаю нулевую ссылку вместо требуемого экземпляра.   -  person Dan    schedule 14.04.2015
comment
DbRepository — это еще одна зависимость от AliasesService, которая удовлетворяется конструктором. Я упрощаю код.   -  person Dan    schedule 14.04.2015
comment
Например, с помощью этой строки: builder.RegisterType‹AliasesService›() .As‹IAliasesService›() .PropertiesAutowired(); Глядя на документ, он должен сработать, но это не так, потому что во время выполнения у меня есть нулевое значение для свойства MailService в AliasesService.   -  person Dan    schedule 14.04.2015
comment
Вы не показали код с реальными инъекциями. Во всяком случае, я подозреваю, что вы не регистрируете контроллеры, чтобы иметь PropertiesAutowired. См. stackoverflow.com/questions/ 3384812/ и stackoverflow.com/questions/5894458/ (ответ от nickvane).   -  person Jacek Gorgoń    schedule 14.04.2015
comment
Когда вы сталкиваетесь с исключением nullref? Вы используете свойство внутри конструктора? Кстати, не могли бы вы поделиться кодом ваших контроллеров и сервисов? (только конструктор и свойства) Это поможет нам понять, что происходит не так, потому что все выглядит нормально   -  person Cyril Durand    schedule 14.04.2015
comment
@JacekGorgoń Я регистрирую контроллеры с помощью PropertiesAutowired, и для контроллеров все работает отлично (я также указал это в разделе «Стоит упомянуть»), но проблема относится к свойству службы, а не к контроллеру.   -  person Dan    schedule 14.04.2015
comment
@CyrilDurand Я добавил немного кода, дайте мне знать, если заметите что-то не так.   -  person Dan    schedule 14.04.2015
comment
@ user2704 Кажется, вы дважды регистрируете свой контроллер, но это не должно быть проблемой. Не могли бы вы поделиться своим AliasesService классом?   -  person Cyril Durand    schedule 14.04.2015
comment
@CyrilDurand Добавлен фрагмент класса.   -  person Dan    schedule 14.04.2015
comment
Можно ли снять статус «В ожидании»?   -  person Dan    schedule 14.04.2015
comment
@ user2704 все выглядит нормально. Не могли бы вы добавить точки останова в конструктор и сеттер и посмотреть на стек вызовов, чтобы проверить, создает ли Autofac эти типы?   -  person Cyril Durand    schedule 15.04.2015
comment
@CyrilDurand Вызывается конструктор AliasesService, конструктор MailService не вызывается.   -  person Dan    schedule 15.04.2015
comment
Является ли вставленный регистрационный код полным? Существует по крайней мере одна известная проблема, связанная с тем, что перехватчики сталкиваются с инъекцией свойств, что приводит к их сбою, но вы, похоже, не используете перехватчики...   -  person Jacek Gorgoń    schedule 15.04.2015
comment
@JacekGorgoń да, все работает, кроме внедрения свойства для сервисов   -  person Dan    schedule 15.04.2015
comment
Этот код выглядит хорошо. Можете ли вы создать минимальный репро и загрузить его куда-нибудь?   -  person Jacek Gorgoń    schedule 15.04.2015


Ответы (3)


В вашем минимальном примере кода свойство Bar объявлено с типом Bar, который не зарегистрирован. Объявленный тип свойства должен быть зарегистрирован, чтобы позволить Autofac разрешить его. Вам следует изменить тип объекта на IBar или зарегистрировать Bar как Bar.

public class Foo : IFoo
{
    public IBar Bar { get; set; }
}

or

builder.RegisterType<Bar>().As<Bar>();
person Cyril Durand    schedule 15.04.2015
comment
Это правда, но минимальное воспроизведение несовместимо с приведенным выше кодом AliasesService, который внедряет IMailService (не MailService). @ user2704: пожалуйста, уточните, какой код вы использовали. Кроме того, вы можете использовать AsSelf(). - person Jacek Gorgoń; 16.04.2015
comment
Это была опечатка, я исправил код и добавил больше деталей. Спасибо за поддержку, ребята. - person Dan; 17.04.2015

Ваш минимальный пример работает нормально, Foo разрешается с помощью введенного экземпляра Bar.

Хотя это не слишком полезно, ваша проблема заключается в другом.

person Jacek Gorgoń    schedule 17.04.2015

хм, ваш пример неверен, потому что AliasesService не реализует интерфейс IAliasesService, но я думаю, что это опечатка.

Ваша реализация MAilService отсутствует. PropertiesAutowired() молча завершает работу, если есть зависимости, которые она не может разрешить.

Так что ваша проблема, вероятно, заключается в MailService

person Jamee    schedule 15.01.2016