C# 基于类型的观察者?

发布于 2024-07-09 04:42:04 字数 1018 浏览 7 评论 0原文

假设我想创建一组基于类型的观察者。 也就是说,当他们收到事件通知时,他们会被告知其中一个参数的类型,然后根据是否可以对该类型进行操作来决定是否采取行动。

有什么简单的方法可以做到这一点吗? 我认为使用泛型来做到这一点相当简单,但这似乎比我想象的要困难。 如果可以避免的话,我宁愿不必处理对对象的一堆引用。

我遇到困难的地方是这样做:

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;
    }
}

当然,我也可以使主题通用,但随后我必须为每种类型设置一个单独的主题。 这里有人有什么建议吗? 我是否在某处遗漏了某些功能,或者我是否过于复杂化了?

更新:我确实过度简化了 Notify 和 NotifyDelegate 所采用的参数。 相反:

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

我实际上想做这样的事情:

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

我基本上试图来回传递的是来自数据库的数据。 如果之前的代码示例让任何人感到困惑,我们深表歉意。

Suppose I want to create a set of observers based on type. That is to say, when they are notified of an event, they are told the type of one of the arguments and then decides whether or not to act based on if it can operate on that type.

Are there any simple ways to do this? I figured this would be fairly simple to do with generics, but that seems to be turning out to be harder than I imagined. And I would prefer not to have to deal with casting a bunch of references to object if I can avoid it.

Where I'm getting stuck is in doing 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 make the Subject generic as well, but then I have to have a separate Subject for each type. Does anyone have any advice here? Is there some piece of functionality that I'm missing somewhere or am I overcomplicating this?

UPDATE: I did oversimplify the arguments that Notify and NotifyDelegate take. Instead of this:

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

I'm actually wanting to do something like this:

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

What I'm basically trying to pass back and forth is data from a database. Sorry if the previous code sample confused anyone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初心未许 2024-07-16 04:42:05

首先,将代码更改为以下内容:

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);
}

First off, change the code you've got to the following:

interface IObserver
{
}

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

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

  List<IObserver>
    m_observers;
}

Then, use reflection to find an appropriate function based on parameter type:

  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;
          }
        }
      }
    }
  }

and use it like this:

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);
}
忘羡 2024-07-16 04:42:05
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));
      }
    }
}
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));
      }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文