5
\$\begingroup\$

I'm designing an entity-component engine in C# right now, and all components need to have access to the global event manager, which sends off inter-entity events (every entity also has a local event manager).

I'd like to be able to simply call functions like this:

GlobalEventManager.Publish("Foo", new EventData());
GlobalEventManager.Subscribe("Bar", OnBarEvent);

without having to do this:

class HealthComponent
{
    private EventManager globalEventManager;

    public HealthComponent(EventManager gEM)
    {
        globalEventManager = gEM;
    }
}

// later on...
EventManager globalEventManager = new EventManager();
Entity playerEntity = new Entity();
playerEntity.AddComponent(new HealthComponent(globalEventManager));

How can I accomplish this?

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Welcome to the site! I am glad you found a solution to your problem. I invite you to put the answer into an actual answer and mark it as the answer. The site more than allows for this :) \$\endgroup\$
    – James
    Mar 19, 2012 at 16:59
  • \$\begingroup\$ I've also removed the "SOLVED" tag from your question, as the proper way to indicate such on this site is to post an answer and accept it, as James said (probably you will need to wait until you question is a few more hours old before the system will let you do so). \$\endgroup\$
    – user1430
    Mar 19, 2012 at 17:12
  • \$\begingroup\$ Yeah, I tried doing that and it said I had to wait 8 more hours. \$\endgroup\$
    – jmegaffin
    Mar 19, 2012 at 17:14
  • 2
    \$\begingroup\$ It's been more than 8 hours :) \$\endgroup\$
    – House
    Oct 8, 2012 at 3:17

3 Answers 3

6
\$\begingroup\$

Although your solution works, you are losing testability by using singleton. In addition you are highly coupled with your global objects. If you will ever think of unit tests for your new components, you will have specially prepare your GlobalEventManager and ensure that your tests are not run in parallel.

One option is to use Factory pattern. Something like:

 playerEntity.AddComponent(componentFactory.createHealth());

Or read about dependency injection frameworks.

\$\endgroup\$
1
\$\begingroup\$

Why not just use C#'s native event system? That way any components that want to subscribe to a component's events can do so from outside the class.

\$\endgroup\$
3
  • \$\begingroup\$ My own system works perfectly well and it's already very similar to C#'s events. The difference is that I have full control over it. I just want a way to call methods from an API object. \$\endgroup\$
    – jmegaffin
    Mar 19, 2012 at 16:32
  • \$\begingroup\$ @Boreal Pass the API object to every object that calls its methods. \$\endgroup\$
    – Zolomon
    Mar 19, 2012 at 16:46
  • \$\begingroup\$ @Boreal Singletons are killer for unit testing, I highly recommend finding a different approach. \$\endgroup\$
    – mike
    Mar 20, 2012 at 10:06
1
\$\begingroup\$

I solved it by creating a singleton called GlobalEventManager. It derives from the local EventManager class and I use it like this:

GlobalEventManager.Instance.Publish("Foo", new EventData());

Thanks Byte :p

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .