简体   繁体   English

如何在接口中声明所需的事件?

[英]How to declare a needed event in an interface?

My console application must be able to get data from two different datasources that must implement an interface named IDataSource . 我的控制台应用程序必须能够从必须实现名为IDataSource的接口的两个不同数据源中获取数据。 When data are received the dataSource object must raise an event named OnHistoricalDataReceived . 接收到数据后,dataSource对象必须引发一个名为OnHistoricalDataReceived的事件。

I created the EventArgs : 我创建了EventArgs

public class HistoricalDataReceivedEventArgs : EventArgs
{
    public IDataSource DataSource {get; set;}
    public string Symbol {get; set;}
    public List<DailyPrice> Data {get;set;}

    public HistoricalDataReceivedEventArgs(IDataSource dataSource, string symbol, List<DailyPrice> data)
    {
        DataSource = dataSource;
        Symbol = symbol;
        Data = data;
    }
}

I created the interface IDataSource : 我创建了接口IDataSource

public interface IDataSource
{
    event EventHandler<HistoricalDataReceivedEventArgs> OnHistoricalDataReceived;
    List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null);
}

Then I created two simple classes, one for Bloomberg and one for Reuters: 然后,我创建了两个简单的类,一个用于彭博社,一个用于路透社:

public class Bloomberg: IDataSource
{
    public delegate void HistoricalDataReceivedEventRaiser(HistoricalDataReceivedEventArgs args);
    public event HistoricalDataReceivedEventRaiser OnHistoricalDataReceived;

    public List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null)
    {
    var data = new List<DailyPrice>(); 

    // ... get the data

    var args = new HistoricalDataReceivedEventArgs(dataSource: this, symbol: symbol, data: data);
        if (OnHistoricalDataReceived!=null)
        {
            OnHistoricalDataReceived(args);
        }
    }
}

public class Reuters: IDataSource
{
    public delegate void HistoricalDataReceivedEventRaiser(HistoricalDataReceivedEventArgs args);
    public event HistoricalDataReceivedEventRaiser OnHistoricalDataReceived;

    public List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null)
    {
        var data = new List<DailyPrice>(); 

    // ... get the data

    var args = new HistoricalDataReceivedEventArgs(dataSource: this, symbol: symbol, data: data);
        if (OnHistoricalDataReceived!=null)
        {
            OnHistoricalDataReceived(args);
        }
    }
}

All the code work If I avoid to put this line in my interface: 所有代码都可以正常工作如果我避免在界面中放置以下行:

event EventHandler<HistoricalDataReceivedEventArgs> OnHistoricalDataReceived;

But I want that every object that implements the interface will raise this event when the data are retrieved. 但是我希望实现该接口的每个对象在检索数据时都会引发此事件。

If I try to compile the compiler complains: 如果我尝试编译,编译器会抱怨:

'Bloomberg' does not implement interface member 'IDataSource.OnHistoricalDataReceived'. “彭博”没有实现接口成员“ IDataSource.OnHistoricalDataReceived”。 'Bloomberg.OnHistoricalDataReceived' cannot implement 'IDataSource.OnHistoricalDataReceived' because it does not have the matching return type of 'EventHandler'. 'Bloomberg.OnHistoricalDataReceived'无法实现'IDataSource.OnHistoricalDataReceived',因为它没有匹配的返回类型'EventHandler'。

'Reuters' does not implement interface member 'IDataSource.OnHistoricalDataReceived'. “路透社”未实现接口成员“ IDataSource.OnHistoricalDataReceived”。 'Reuters.OnHistoricalDataReceived' cannot implement 'IDataSource.OnHistoricalDataReceived' because it does not have the matching return type of 'EventHandler'. “ Reuters.OnHistoricalDataReceived”无法实现“ IDataSource.OnHistoricalDataReceived”,因为它没有匹配的“ EventHandler”返回类型。

I tried many variation without any success. 我尝试了许多变化,但没有成功。 What is the right way to specify in my interface I want the OnHistoricalDataReceived event? 在我的界面中指定我想要OnHistoricalDataReceived事件的正确方法是什么?

You need to implement the event in your classes, but instead you created two new delegate types and used them as the event's type. 您需要在您的类中实现该事件,但是您创建了两个新的委托类型并将它们用作事件的类型。

You implement the event just like you declared it in the interface: 您可以按照在接口中声明的方式实现事件:

public class Bloomberg: IDataSource
{
    public event EventHandler<HistoricalDataReceivedEventArgs> OnHistoricalDataReceived;

    public List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null)
    {
        var data = new List<DailyPrice>(); 

        // ... get the data

        var args = new HistoricalDataReceivedEventArgs(dataSource: this, symbol: symbol, data: data);
        if (OnHistoricalDataReceived!=null)
        {
            OnHistoricalDataReceived(this, args); // use "this" as sender
        }
    }
}

public class Reuters: IDataSource
{
    public event EventHandler<HistoricalDataReceivedEventArgs> OnHistoricalDataReceived;

    public List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null)
    {
        var data = new List<DailyPrice>(); 

        // ... get the data

        var args = new HistoricalDataReceivedEventArgs(dataSource: this, symbol: symbol, data: data);
        if (OnHistoricalDataReceived!=null)
        {
            OnHistoricalDataReceived(this, args); // use this as sender
        }
    }
}

Note that (in C#6) you can do this: 请注意 (在C#6中),您可以执行以下操作:

OnHistoricalDataReceived?.Invoke(this, args);

This is thread-safe. 这是线程安全的。 Your current code can break if the event is unsubscribed by another thread again after the null-check. 如果执行空检查再次由另一个线程取消订阅该事件,则当前代码可能会中断。

Before C# 6 you should have done this: 在C#6之前,您应该这样做:

var handler = OnHistoricalDataReceived; // save the reference
if (handler != null) handler(this, args); // use the local (unchanged) variable

Please change your interface to: 请将您的界面更改为:

public interface IDataSource
{
    event HistoricalDataReceivedEventRaiser OnHistoricalDataReceived;
    List<DailyPrice> RequestHistoricalData(string symbol, List<PriceField> fields, DateTime? firstDate=null, DateTime? lastDate=null);
}

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

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