事件+适配器模式

时间:2011-01-13 03:11:40

标签: c# adapter

我在泛型类上有一个适配器模式,它基本上适应不同类型:

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的事件分配给。

我怀疑有任何简单的方法,但也许有人有一些想法让它发挥作用。

(顺便说一下,我意识到虚拟事件可以实现这一点,但我想尽可能避免这种情况)

3 个答案:

答案 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");
        }

    }
}

(编辑:代码现在包含一个新方法,它将事件包装在一个类中,现在允许轻松分配事件并有效地表示“指针”的情况。希望有人可以进一步改进这些。)