Как решить проблему с вводом свойств с помощью Autofac?
У меня есть веб-приложение MVC, которое использует Autofac для внедрения служб в контроллеры.
Проблема: я пытаюсь выполнить инъекцию свойства в сервис, и он не работает (свойство всегда имеет значение null).
Что я ожидаю: я ожидаю, что свойство будет инициализировано должным образом (не 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();
}
}
Global.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));
AliasesService:
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, и он делает все, что мне нужно, спасибо за поддержку.
3 ответа
Ваш минимальный пример работает нормально, Foo разрешается с добавленным экземпляром Bar.
Хотя это не слишком полезно, ваша проблема лежит в другом месте.
В вашем минимальном примере кода свойство Bar объявлено с типом Bar
который не зарегистрирован. Объявленный тип свойства должен быть зарегистрирован, чтобы позволить Autofac разрешить его. Вы должны изменить тип свойства на IBar
или зарегистрируйтесь Bar
как Bar
public class Foo : IFoo
{
public IBar Bar { get; set; }
}
или же
builder.RegisterType<Bar>().As<Bar>();
Хм, ваш пример неверен, потому что AliasesService не реализует интерфейс IAliasesService, но я думаю, что это опечатка.
Ваша реализация MAilService отсутствует. PropertiesAutowired() молча завершается ошибкой, если есть зависимости, которые она не может разрешить.
Так что ваша проблема, вероятно, заключается в MailService