title: Listen for event and invoke callback, based on specification?
body: <p>I am currently building out a custom task manager and I'm wondering if it's possible to tell the task manager to listen for a specific event (<code>OnSomething</code> below), and then invoke a callback method when the task raises that event. However, mentally I can't see how it's possible to listen for an event that doesn't exist at the base class level. For example, I have a base class that contains basic information about the task called <code>CustomTask</code>:</p>
  <pre><code>public abstract class CustomTask {
      public bool IsRunning { get; private set; } = false;
      public void Start() {
          IsRunning = true;
          DoSomething();
          IsRunning = false;
      }
      protected abstract void DoSomething();
  }
  </code></pre>
  <p>For the sake of SO readers, I've simplified the definition, but you get the gist of it. It contains basic details, a few methods for starting and canceling, provides basic state management (simplified <code>IsRunning</code> here), etc.</p>
  <p>I then have custom tasks that derive from <code>CustomTask</code>, in this case, let's focus on a sample task called <code>CustomTaskA</code>. It contains a definition for an event called <code>OnSomething</code>, which someone, somewhere may want to listen for:</p>
  <pre><code>public sealed class CustomTaskA : CustomTask {
      protected override void DoSomething() =&gt; RaiseOnSomething(this, new EventArgs());
      public event EventHandler&lt;EventArgs&gt; OnSomething;
      private void RaiseOnSomething(object sender, EventArgs e) =&gt; OnSomething?.Invoke(sender, e);
  }
  </code></pre>
  <p>Now, the <code>CustomTaskManager</code> registers tasks, tracks them via <code>Guid</code>, manages them and more, but for simplicity:</p>
  <pre><code>public sealed class CustomTaskManager {
      // Singleton setup.
      private static CustomTaskManager _instance = new CustomTaskManager();
      public static CustomTaskManager Instance {
          get {
              // Simplified for SO.
              if (_instance == null)
                  _instance = new CustomTaskManager();
  
              return;
          }
      }
  
      // Collection of tasks.
      private Dictionary&lt;Guid, CustomTask&gt; _tasks = new Dictionary&lt;Guid, CustomTask&gt;();
  
      // Register and start a task.
      public bool TryRegisterAndStartTask(CustomTask task, out Guid taskId) {
          taskId = Guid.Empty;
          try {
              // Register task.
              taskId = Guid.NewGuid();
              _tasks.Add(taskId, task);
  
              // Listen for events.
  
              // Start task.
              task.Start();
          } catch (Exception e) {
              // Log exception.
          }
  
          return false;
      }
  }
  </code></pre>
  <p>When registering and starting a task, I'd like to tell the task manager I want to listen for <code>OnSomething</code>, and if <code>OnSomething</code> is invoked, I want the task manager to call a method <code>OnSomethingWasRaised</code>. For example:</p>
  <pre><code>TaskManager.Instance.TryRegisterAndStartTask(task, out Guid taskId, task.OnSomething, OnSomethingWasRaised);
  
  private static void OnSomethingWasRaised(object sender, EventArgs e) {
      Console.WriteLine(&quot;Woohoo!&quot;);
  }
  </code></pre>
  <p>I know the specifying and invoking a callback method is entirely possible, and listening for events is plausible with reflection.</p>
  <hr />
  <p>Is there a way (with or without using reflection) to listen for a specified event defined on a derived object and then invoke a specified callback method?</p>
  <p><strong>NOTE</strong>: Please excuse any syntactical errors as I hand-typed the snippets to keep them minimal.</p>