基于类型的C#观察者?
问题描述:
假设我想根据类型创建一组观察者。也就是说,当他们被通知一个事件时,他们被告知其中一个参数的类型,然后根据是否可以操作该类型来决定是否采取行动。基于类型的C#观察者?
有没有简单的方法可以做到这一点?我认为这对于泛型会很简单,但似乎要比我想象的要困难。如果我可以避免的话,我宁愿不必处理投射一堆对象的引用。
当我陷入在这样做:
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;
}
}
当然,我可以使主题一般为好,但我必须为每个类型都有一个单独主题。有没有人有任何建议吗?有什么功能可以让我在某个地方失踪,或者我是否过于复杂?
UPDATE:我没有简化Notify和NotifyDelegate的参数。取而代之的是:
public delegate void NotifyDelegate<T>(NotifyArgs na);
实际上,我想要做这样的事情:
public delegate void NotifyDelegate<T>(IEnumerator<T> loadable, NotifyArgs na);
什么基本上,我试图通过来回数据库中的数据。对不起,如果以前的代码示例困惑任何人。
答
首先,更改代码,你有以下几点:
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);
}
答
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));
}
}
}
有趣的想法。这比我想要实现的要复杂一点,但至少在我无法找出更简单的方法时,它看起来会起作用。 – 2008-11-17 16:24:01