如何在界面中声明所需的事件?

时间:2017-03-21 12:11:20

标签: c#

我的控制台应用程序必须能够从两个必须实现名为IDataSource的接口的不同数据源中获取数据。收到数据时,dataSource对象必须引发名为OnHistoricalDataReceived的事件。

我创建了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;
    }
}

我创建了界面IDataSource

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

然后我创建了两个简单的类,一个用于Bloomberg,另一个用于路透社:

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);
        }
    }
}

所有代码都工作如果我避免将这一行放在我的界面中:

event EventHandler<HistoricalDataReceivedEventArgs> OnHistoricalDataReceived;

但我希望实现接口的每个对象都会在检索数据时引发此事件。

如果我尝试编译编译器抱怨:

  

'Bloomberg'没有实现接口成员'IDataSource.OnHistoricalDataReceived'。   'Bloomberg.OnHistoricalDataReceived'无法实现   'IDataSource.OnHistoricalDataReceived'因为它没有   匹配'EventHandler'的返回类型。

     

'路透社'没有实现接口成员'IDataSource.OnHistoricalDataReceived'。   'Reuters.OnHistoricalDataReceived'无法实现   'IDataSource.OnHistoricalDataReceived'因为它没有   匹配'EventHandler'的返回类型。

我尝试了很多变化而没有任何成功。在我的界面中指定我想要OnHistoricalDataReceived事件的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

您需要在类中实现事件,而是创建两个新的委托类型并将它们用作事件的类型。

您实现事件就像在界面中声明它一样:

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
        }
    }
}

注意(在C#6中)你可以这样做:

OnHistoricalDataReceived?.Invoke(this, args);

这是线程安全的。如果在空检查后再次取消该事件,则当前代码可能会中断。

在C#6之前你应该这样做:

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

答案 1 :(得分:0)

请将您的界面更改为:

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