Как написать EventManager/Observer на много событий без Reflection?
В C# уже есть механизм событий, прячущий под капот паттерн Observer.
См. ключевое слово event.
А вообще switch в методе Update можно заменить на паттерн ServiceLocator, по сутиpublic class EventManager
{
  Dictionary<EventType, EventHandler> handlerLocator.
  public void RegisterEventHandler(EventType type, EventHandler handler)
  {
    this.handlerLocator[type] = handler;
  }

  public void Update(Event e)
  {
    var handler = this.handlerLocator[e.Type];
    handler(this, e.EventArgs);
  }
}
Можно написать абстрактный класс, в котором будут пустые реализации OnEvent для каждого события, а в наследниках уже их переопределять при необходимости. Например так:class EventManager
{
    List<EventListenerBase> listeners = new List<EventListenerBase>();

    public void Subscribe(EventListenerBase listener)
    {
        listeners.Add(listener);
    }

    public void Publish(Event e)
    {
        foreach (EventListenerBase listener in listeners)
        {
            listener.OnEvent(e);
        }
    }

    public void Publish(MoveEvent e)
    {
        foreach (EventListenerBase listener in listeners)
        {
            listener.OnEvent(e);
        }
    }

    public void Publish(BuildEvent e)
    {
        foreach (EventListenerBase listener in listeners)
        {
            listener.OnEvent(e);
        }
    }
}

abstract class EventListenerBase
{
    public virtual void OnEvent(Event e)
    {
            
    }

    public virtual void OnEvent(MoveEvent a)
    {
            
    }

    public virtual void OnEvent(BuildEvent a)
    {
            
    }
}

class GameHandler : EventListenerBase
{
    public override void OnEvent(Event e)
    {
        Debug.WriteLine("Event");
    }

    public override void OnEvent(BuildEvent a)
    {
        Debug.WriteLine("BuildEvent");
    }

    public override void OnEvent(MoveEvent a)
    {
        Debug.WriteLine("MoveEvent");
    }
}
Но этот способ отвратителен, никогда его не используйте :) Хотя бы потому что для каждого события нужно делать отдельный метод OnEvent и Publish, и работает это только в статике, компилятор выбирает нужный метод во время компиляции, т.е. manager.Publish((Event) new MoveEvent()) не вызовет обработчик для MoveEvent.
Такие вещи (и в Java и в C#) лучше делать рефлексией или с помощью Expression в C#. О производительности Reflection можно не беспокоиться, т.к. регистрировать обработчики достаточно все один раз.