Can someone explain pros and cons of Event Bus in Orchard?

Topics: Core, General
Apr 12, 2013 at 7:47 AM
Edited Apr 12, 2013 at 4:29 PM
I've read the code about Event Bus in Orchard, it's really complex and amazing. After reading this code, I have a question: What's the defferences between Event Bus and Injecting IEnumerable<T>?

To clarify, in class DefaultContentManager, the injected IEnumerable<IContentHandler> field invokes events in relative methods. But in class ContentDefinitionService, it just injects one IContentDefinitionEditorEvents in Event Bus way, instead of Injecting a IEnumerable<T>.

It looks like they do the same thing. The only difference I can tell between these two approaches is having IEnumerable<> or not. I believe I must have missed something important.

So why does Orchard need Event Bus if they are the same? Or if Event Bus is certainly good, why didn't we use it in every place?

Can someone explain it to me? thanks in advance.
Developer
Apr 12, 2013 at 1:20 PM
Apr 12, 2013 at 4:13 PM
Edited Apr 12, 2013 at 4:40 PM
I had already read your article before and I had read all codes about Event Bus -- "EventsModule", "EventsRegistrationSource", "EventsInterceptor", "IEventBus", and so on. I think I've understood how it works and how to use it.
Define a interface "InterfaceA" derived from IEventHandler , So if you call some method on any InterfaceA, the event bus will call the same method on all other implementations of InterfaceA.

But my question is I could implement the same functionality by Injecting an enumerable of InterfaceB that don't have to derive from IEventHandler , like IEnumerable<IContentHandler> in class "DefaultContentManager".

So my point is if I can type code like this, why do I need Event Bus?

As you mentioned in your article, you made a mistake that you injected an enumerable of IOrderEventHandler at the beginning. So is it the only difference ? Don't need to make interface enumerable ? At the end it's completely equivalent?
Apr 12, 2013 at 10:54 PM
for injecting, u should refer InterfaceA.
but for bus, u do not need. all other implementations can spread out any modules, even the modules in future. loosely!!!! n maybe can avoid recursive reference.
Apr 13, 2013 at 1:00 AM
Edited Apr 13, 2013 at 11:07 AM
infofromca wrote:
for injecting, u should refer InterfaceA.
but for bus, u do not need. all other implementations can spread out any modules, even the modules in future. loosely!!!! n maybe can avoid recursive reference.
public interface IOrderEventHandler : IEventHandler {
        void OrderCreated(OrderCreatedContext context);
}

public interface IOrderNoEventHandler: IDenpendency{
        void OrderCreated(OrderCreatedContext context);
}

public class OrderManager : Component, IOrderManager {
        private readonly IOrderEventHandler _orderEventHandler;
        private readonly IEnumerable<IOrderNoEventHandler> _orderNoEventHandler;
 
        public OrderManager(IOrderEventHandler orderEventHandler) {
            _orderEventHandler = orderEventHandler;
        }
 
        public Order CreateOrder(int customerId) {
            var order = new Order();
            var context = new OrderCreatedContext(order);

            _orderEventHandler.OrderCreated(context); 
            _orderNoEventHandler.Invoke(handler => handler.OrderCreated(context ), Logger); 

            return order;
        }
    }
In above code, I think IOrderEventHandler and IOrderNoEventHandler do the same thing.
Invoke is a static extension method. This code just like IEnumerable<IContentHandler> in class "DefaultContentManager".

Users will be able to create an implementation of IOrderEventHandler and extend the functionality of our module without having to touch our code.
So does IOrderNoEventHandler !!

What's the defferences then? if you prefer IOrderEventHandler, why?

if I want to create a implementation of these two interface, I have to refer them. But you said I don't need to do that for bus, Could you explain more further?
Coordinator
Apr 14, 2013 at 5:08 AM
Interfaces are matched by name, not by strong type, which means that you don't need to reference another assembly in order to be able to implement event handlers. Also, the interface matching is just one implementation for the event bus, but you could swap it out for something that is, for example, distributed.