#asp.net-mvc #autofac #mediatr #eventaggregator
#asp.net-mvc #autofac #mediatr #eventaggregator
Вопрос:
Мне нужен простой EventAggregator в моем ASP.NET Приложение MVC, в котором я использую AutoFac. Я взглянул на https://github.com/NimaAra/Easy.MessageHub — Мне очень нравится простота и легкий вес, поскольку я чувствую, что полная реализация сервисной шины может быть излишней для моих нужд. Но я весь внимание, если у кого-то есть лучший подход 🙂
Однако, похоже, я не могу настроить настройку для работы с моим веб-приложением. У меня очень простая настройка:
HomeController (просто для инициирования вызова)
public class HomeController : Controller
{
private readonly IPublishStuffService _publishStuffService;
private readonly IMessageHub _hub;
public HomeController(IPublishStuffService publishStuffService, IMessageHub hub)
{
_publishStuffService = publishStuffService;
_hub = hub;
_hub.RegisterGlobalHandler((type, eventObject) => Debug.WriteLine($"Type: {type} - Event: {eventObject}"));
}
public ActionResult Index()
{
_publishStuffService.PublishStuff("Hello world");
return View();
}
}
PublishStuffService
public class PublishStuffService : IPublishStuffService
{
private readonly IMessageHub _hub;
public PublishStuffService(IMessageHub hub)
{
_hub = hub;
}
public void PublishStuff(string message)
{
_hub.Publish(message);
}
}
SubscribeToStuffService
public class SubscribeToStuffService : ISubscribeToStuffService
{
private readonly IMessageHub _hub;
public SubscribeToStuffService(IMessageHub hub)
{
_hub = hub;
_hub.Subscribe<string>(HandleSubscription);
}
public void HandleSubscription(string message)
{
Debug.WriteLine("===================");
Debug.WriteLine(message);
Debug.WriteLine("===================");
}
}
Мой GlobalHandler нормально выводит сообщение «Hello world», но моя служба подписки никогда не вызывается. Я полагаю, что это может быть проблемой с моей настройкой AutoFac, но я не уверен, как справиться с ситуацией.
Моя конфигурация AutoFac (с использованием AutoFac.MVC5) выглядит следующим образом:
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(HomeController).Assembly);
builder.RegisterModelBinders(typeof(HomeController).Assembly);
builder.RegisterModelBinderProvider();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterFilterProvider();
// Register individual components
builder.RegisterType(typeof(SubscribeToStuffService)).As<ISubscribeToStuffService>().InstancePerLifetimeScope();
builder.RegisterType(typeof(PublishStuffService)).As<IPublishStuffService>().InstancePerLifetimeScope();
builder.RegisterType(typeof(MessageHub)).As<IMessageHub>().SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Кто-нибудь может помочь мне выяснить, как обеспечить сохранение концентратора сообщений во всем моем веб-приложении, чтобы у меня были разные классы, подписывающиеся на разные события, опубликованные в концентраторе сообщений.
По сути, я ищу часть уведомлений библиотеки Mediatr Джимми Богарда, которая, кстати, работает идеально, но я чувствую, что реализация Mediatr может быть немного сложной, если я собираюсь использовать только настройку уведомлений 🙂
ОБНОВЛЕНИЕ Я действительно могу запустить события подписчика, если добавлю зависимость к ISubscribeToStuffService в том же месте, где я публикую (здесь, в моем HomeController):
public class HomeController : Controller
{
private readonly IPublishStuffService _publishStuffService;
private readonly IMessageHub _hub;
private readonly ISubscribeToStuffService _subscribeToStuffService;
public HomeController(IPublishStuffService publishStuffService, IMessageHub hub, ISubscribeToStuffService subscribeToStuffService)
{
_publishStuffService = publishStuffService;
_hub = hub;
_subscribeToStuffService = subscribeToStuffService;
}
...
}
Это, по-видимому, устраняет подписчика. Но это не очень полезно, поскольку это противоречит цели иметь слабую связь между моими зависимостями.
Итак, возникает вопрос: как мне заставить AutoFac разрешать моих подписчиков без необходимости добавлять их в качестве зависимостей везде, где я публикую что-то в шине сообщений? Можно ли это сделать?
В ОБНОВЛЕНИИ 2 найдено это изящное маленькое расширение pub / sub для AutoFac: https://github.com/jonstelly/AutofacEvents . Он делает все, что мне нужно, прямо из коробки с точки зрения запуска и запуска агрегатора событий с AutoFac.
Комментарии:
1. Здесь отсутствует некоторая информация. Я никогда не использовал EventAggregator, но вы не показываете людям, где на самом
ISubscribeToStuffService
деле используется / создается экземпляр. Из этого… не похоже, что он когда-либо используется, и если он никогда не создается (и, я бы предположил, активен при публикации сообщения), то он не будет реагировать на событие, верно? Может быть? Опять же, я не специалист по EventAggregator, поэтому, вероятно, здесь не смогу помочь.2. Идея состоит в том, чтобы не создавать тесную связь между различными частями приложения. Таким образом, в основном концентратор сообщений / служебная шина (как бы вы ее ни называли) должна содержать информацию о событиях, публикуемых в нем, — и затем подписчики должны автоматически вызываться — без необходимости их использования. Таким образом, в принципе, я мог бы выполнить несколько разных действий при возникновении события (например, при событии «Пользователь создан» я мог бы отправить пользователю приветственное электронное письмо, а также уведомление в бухгалтерию).). Но я не могу заставить подписчиков подключиться к AutoFac:(
3. @TravisIlligbut вы правы в результате (и, вероятно, также в причине) — ISubscribeToStuff (и любые другие подписчики), похоже, не являются «живыми» или инициированными. Но я предполагаю, что это потому, что я неправильно настроил свой IoC, чтобы это работало (или у кого-то еще может быть лучшее предложение).
4. Это вопрос дизайна приложения, а не IoC. В обязанности Autofac не входит выяснять, как и когда нужно создавать экземпляры ваших подписчиков — это код приложения. Когда вам нужны экземпляры из кода вашего приложения — это IoC.