C # type-based observers?

Suppose I want to create a set of observers based on a type. That is, when they are notified of the event, they are informed of the type of one of the arguments, and then decides whether to act or not, based on whether it can work with this type.

Are there any simple ways to do this? I figured it would be pretty easy to do with generics, but it seems to be harder than I imagined. And I would prefer not to deal with casting a reference to an object if I can avoid it.

Where am I stuck with this:

public delegate void NotifyDelegate<T>(IEnumerator<T> loadable, NotifyArgs na);

interface IObserver
{
    void Notify<T>(IEnumerator<T> loadable, NotifyArgs na);
}

class Subject
{
    NotifyDelegate notifier;  //won't compile:  needs type args

    void Register(IObserver o)
    {
        notifier += o.Notify;
    }
}

Of course, I could also create a Subject theme, but then I should have a separate Subject for each type. Anyone have any advice? Is there some kind of functionality that I am missing somewhere, or am I violating it too much?

. , Notify NotifyDelegate. :

public delegate void NotifyDelegate<T>(NotifyArgs na);

- :

public delegate void NotifyDelegate<T>(IEnumerator<T> loadable, NotifyArgs na);

, , . , -.

+3
2

, , , :

interface IObserver
{
}

class Subject
{
  public Subject ()
  {
    m_observers = new List<IObserver> ();
  }

  public void Register (IObserver o)
  {
    m_observers.Add (o);
  }

  List<IObserver>
    m_observers;
}

, , :

  public void NotifyObservers (object param)
  {
    foreach (IObserver observer in m_observers)
    {
      foreach (MethodInfo method in observer.GetType ().GetMethods (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance))
      {
        if (method.Name == "Notify")
        {
          ParameterInfo []
            parameters = method.GetParameters ();

          if (parameters.Length == 1 && parameters [0].ParameterType == param.GetType ())
          {
            method.Invoke (observer, new object [] { param });
            break;
          }
        }
      }
    }
  }

:

class Observer : IObserver
{
  public Observer (Subject s)
  {
    s.Register (this);
  }

  void Notify (float value)
  {
    System.Diagnostics.Trace.WriteLine ("float value = " + value);
  }

  void Notify (int value)
  {
    System.Diagnostics.Trace.WriteLine ("int value = " + value);
  }
}

static void Main (string [] args)
{
  Subject
    s = new Subject ();

  Observer
    o = new Observer (s);

  float
    v1 = 3.14f;

  int
    v2 = 42;

  System.Diagnostics.Trace.WriteLine ("sending float");
  s.NotifyObservers (v1);
  System.Diagnostics.Trace.WriteLine ("sending int");
  s.NotifyObservers (v2);
}
+3
interface IObserver
{
    void Notify(NotifyArgs na);
    bool SupportsType(Type t);
}

class Subject
{
    List<IObserver> observers;

    void Register(IObserver o)
    { observers.Add(o);
    }

   void OnNotify(Type t, NotifyArgs args)
    {
      foreach (IObserver o in observers)  
      {
        if (o.SupportsType(t)) o.Notify(args));
      }
    }
}
+2

Source: https://habr.com/ru/post/1699667/


All Articles