繁体   English   中英

是否可以实现C#接口并扩展事件的参数?

[英]Is it possible to implement a C# Interface and extend the arguments of Events?

假设我有以下界面:

interface IBook
{
    event EventHandler<EventArgs> PageChanged;
}

我可以在本课程中轻松实现:

class Novel : IBook
{
    public event EventHandler<EventArgs> PageChanged;

    protected void OnPageChanged()
    {
        EventHandler<EventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, EventArgs.Empty);
    }
}

但是,如果我现在有一个称为Encyclopedia的对象定义为:

class Encyclopedia : IBook
{
    public class EncyclopediaEventArgs : EventArgs
    {
        public int Volume
        {
            get { return volume; }
        }

        private int volume;

        public EncyclopediaEventArgs(int volume)
        {
            this.volume = volume;
        }
    }

    public event EventHandler<EncyclopediaEventArgs> PageChanged;

    protected void OnPageChanged(int volume)
    {
        EventHandler<EncyclopediaEventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(volume));
    }
}

它具有Book所有功能,但具有Volume的添加的事件参数字段。 当我编译时,我得到一个错误(我猜想是这样):

错误CS0738:“百科全书库”未实现接口成员“ IBook.PageChanged”。 'Encyclopedia.PageChanged'无法实现'IBook.PageChanged',因为它没有匹配的返回类型'System.EventHandler'

它声明它不能实现IBook.PageChanged因为System.EventHandler<System.EventArgs>不是返回类型,即使EncyclopediaEventArgs派生自System.EventArgs

因此,我的问题是,是否有可能派生出诸如Encyclopedia类的类,该类将附加的Volume字段添加到其事件参数中?

(关于为什么这是一个糟糕的设计/体系结构决定,任何讨论都非常受欢迎!)

这样做似乎很简单:

interface IBook<T> where T : EventArgs
{
    event EventHandler<T> PageChanged;
}

class Novel : IBook<EventArgs> { ... }

class Encyclopedia : IBook<Encyclopedia.EncyclopediaEventArgs> { ... }

如果您仍然需要普通的IBook则可以执行以下操作:

interface IBook { }

interface IBook<T> : IBook where T : EventArgs
{
    event EventHandler<T> PageChanged;
}

这取决于您将如何使用IBook 您可以像这样为EventArgs创建通用参数:

public interface IBook<TEventArgs> where TEventArgs : EventArgs
{
    event EventHandler<TEventArgs> PageChanged;
}

public class Novel : IBook<EventArgs>
{
    event EventHandler<EventArgs> PageChanged;
}

public class Encyclopedia : IBook<EncyclopediaEventArgs>
{
    event EventHandler<EncyclopediaEventArgs> PageChanged;
}

但你不能使用IBook没有泛型类型,如果你需要PageChanged用于其他目的。

另一种方法是只保留event EventHandler<EventArgs> PageChanged; 让Encyclopedia实现传递一个EncyclopediaEventArgs并将其强制转换为事件处理程序。

class Encyclopedia : IBook
{
    public class EncyclopediaEventArgs : EventArgs
    {
    }

    public event EventHandler<EventArgs> PageChanged;

    protected void OnPageChanged(int volume)
    {
        EventHandler<EventArgs> pageChanged = PageChanged;
        if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(...));
    }
}

public class BookReader
{
    public void OnPageChanged(object sender, EventArgs e)
    {
        if (sender is Encyclopedia && e is EncyclopediaEventArgs)
        {
            EncyclopediaEventArgs ee = (EncyclopediaEventArgs)e;
        }
        else
        {
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM