我在泛型类上有一个适配器模式,它基本上适应不同类型:
class A<T> { event EventHandler e; }
class Aadapter<T1, T2> : A<T1> { A<T2> a; Aadapter(A<T2> _a) { a = _a; } }
问题是A包含一个事件。我实际上希望分配给适配器的所有事件处理程序都可以通过。
如果我可以将a的事件处理程序分配给适配器的事件处理程序,那会很棒吗但是这是不可能的?
这里的想法是A几乎真的只是A,但我们需要一种方法来适应它们。由于事件的工作方式,除了手动添加两个事件处理程序之外,我无法如何有效地执行它,当它们被调用时,它们将“中继”到另一个事件。这不是很漂亮,如果我能有类似
的东西,它会更好看class A<T> { event EventHandler e; }
class Aadapter<T1, T2> : A<T1> { event *e; A<T2> a; Aadapter(A<T2> _a) { a = _a; e = a.e; } }
从某种意义上说,我们有一个指向事件的指针,我们可以将a2的事件分配给。
我怀疑有任何简单的方法,但也许有人有一些想法让它发挥作用。
(顺便说一下,我意识到虚拟事件可以实现这一点,但我想尽可能避免这种情况)
答案 0 :(得分:2)
我认为这就是你所追求的目标:
class A<T>
{
public virtual event EventHandler e;
}
class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
Aadapter(A<T2> _a) { a = _a; }
public override event EventHandler e
{
add { a.e += value; }
remove { a.e -= value; }
}
}
或链接
class A<T>
{
public event EventHandler e;
protected void ChainEvent(object sender, EventArgs eventArgs)
{
e(sender, eventArgs);
}
}
class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
Aadapter(A<T2> _a)
{
a = _a;
a.e += ChainEvent;
}
}
答案 1 :(得分:0)
为什么订阅和转发事件不是很好?我发现它很优雅。
执行此操作与实现适配器的其余部分的方式一致。
即使你可以使用指针,它也会不一致,因为你不想在每种情况下都这样做。
例如,如果您正在将实现INotifyPropertyChanged
的类调整到没有实现PropertyChanged
的接口,但是暴露了一些属性,例如“TitleChanged”和“MaxLengthChanged”,那么您将不会使用一个指针。您的适配器将公开这两个事件,消费者将订阅。您的适配器将订阅{{1}}事件,并仅在收到“Title”被修改通知时才会引发“TitleChanged”,并且只有在收到“MaxLength”被修改通知时才会引发“MaxLengthChanged”。所有其他通知都将被忽略。
我赞成这种方法,因为我觉得这种方式直截了当,一致且真实。
答案 2 :(得分:0)
显示解决问题的“标准”方法的示例。第一个使用虚拟事件/方法,而第二个使用“双端”转发方案。两者都有他们的专业和缺点,但如果有一个更容易的方法没有随着事件的数量增长,那将是很好的。我们想要做的是将两个事件直接组合成一个而不是间接组合,这就是所有这些代码所做的事情。 (如果在C#中可能的话,指针就是这样的方法)
//#define __virtual
#define __direct
using System;
using System.Collections.Generic;
using System.Text;
namespace VirtualEvents
{
#if __virtual
#region
public class A<T>
{
public virtual event EventHandler e;
public virtual void Fire() { e(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public override event EventHandler e
{
add { a.e += new EventHandler(value); }
remove { a.e -= new EventHandler(value); }
}
public override void Fire()
{
a.Fire();
}
public Aadapter(A<T2> _a)
{
a = _a;
}
}
#endregion
#elif __direct
#region
public delegate EventHandler EventHandlerPtr();
public class eventPtr
{
public EventHandler _event;
}
public class A<T>
{
//internal EventHandler _event;
public eventPtr _event = new eventPtr();
public event EventHandler e
{
add { _event._event += value; }
remove { _event._event -= value; }
}
public void Fire() { _event._event(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public Aadapter(A<T2> _a)
{
a = _a;
this._event = a._event;
}
}
#endregion
#else
#region
public class A<T>
{
public event EventHandler e;
public void Fire() { e(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public Aadapter(A<T2> _a)
{
a = _a;
a.e += new EventHandler(a_e);
e += new EventHandler(Aadapter_e);
}
void Aadapter_e(object sender, EventArgs e)
{
a.e -= new EventHandler(a_e);
a.Fire();
a.e += new EventHandler(a_e);
}
void a_e(object sender, EventArgs e)
{
this.e -= new EventHandler(Aadapter_e);
Fire();
this.e += new EventHandler(Aadapter_e);
}
}
#endregion
#endif
class Program
{
static void Main(string[] args)
{
var a = new A<double>();
var q = new Aadapter<int, double>(a);
a.e += new EventHandler(a_e);
q.e += new EventHandler(q_e);
a.Fire();
q.Fire();
((A<int>)q).Fire();
Console.ReadKey();
}
static void a_e(object sender, EventArgs e)
{
Console.WriteLine("From a");
}
static void q_e(object sender, EventArgs e)
{
Console.WriteLine("From q");
}
}
}
(编辑:代码现在包含一个新方法,它将事件包装在一个类中,现在允许轻松分配事件并有效地表示“指针”的情况。希望有人可以进一步改进这些。)