如何使用委托跨类触发事件? [英] How to trigger an event across classes using delegates?

查看:101
本文介绍了如何使用委托跨类触发事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个不同的类,需要在main方法中订阅事件。但是我没有在main方法中订阅事件。有人知道怎么做吗?

I have 2 different classes and need to subscribe the event in main method.But I don't get subscribe the event in main method.Is any one know how to do it?

First Class
***********
public class Data
{
    public string ID { get; set; }
    public string Description { get; set; }
}

public class ClsSub
{
    public delegate void datahandler(Data dt);

    public event LogHandler OnDataRetrieved;

    public void LoadData()
    {
        DataTable dt = GetData();
        Data logdata = new Data ();

        foreach (DataRow row in dt.Rows)
        {
           if(row["Description"].ToString().Contains("User Data"))
           {
               logdata.ID = row["UserID"].ToString();
               logdata.Description = row["Description"].ToString();
           }  

           if (OnDataRetrieved != null)
           {
               OnDataRetrieved(logdata );
           } 
        }
    }
}        

Second class
************
Public class ClsMain
{
    public void ReadData()
    {
        ClsSub sub= new ClsSub();
        sub.LoadData()
    }
}


Main Method
***********
public class Program
{
    static void Main(string[] args)
    {
        ClsMain main= new ClsMain();
        main.OnDataRetrieved += ClsMain_OnDataRetrieved;
        main.ReadData();
        Console.ReadKey();
    }

private static void ClsApplication_OnDataRetrieved(Data log)
{
    Console.WriteLine(log.ID  "\t" log.Description)
}


我需要将在ClsMain类中发布的数据订阅到

I need to subscribe the data published in ClsMain class to the main method.How to subscrine that event in main method?

推荐答案

这可能会解决您的问题:

This may address your question:

一个类不能订阅另一个未知的事件。
类也不能订阅不存在的事件。

A class can't subscribe to an event in another class that it doesn't know about. A class also can't subscribe to an event that doesn't exist.

Main 创建 ClsMain 的新实例,然后尝试预订其 OnDataRetrieved 事件。

Main creates a new instance of ClsMain, and then attempts to subscribe to its OnDataRetrieved event.

    ClsMain main= new ClsMain();
    main.OnDataRetrieved += OnDataRetrieved;
    main.ReadData();
    Console.ReadKey();

最初的问题是 ClsMain 不会发生任何此类事件,因此无法订阅。

The initial problem is that ClsMain does not have any such event, so it's impossible to subscribe to it.

ClsSub 确实存在此类事件。但是您的应用程序未使用 ClsSub 的实例。它使用的是 ClsMain 。它不知道 ClsMain 创建一个 ClsSub 的实例,这很好。它不应该知道 ClsMain 方法内部的内容。这样,如果该类的内部更改,您的程序仍然可以使用。

ClsSub does have such an event. But your application isn't using an instance of ClsSub. It's using ClsMain. It doesn't know that ClsMain creates an instance of ClsSub, and that's good. It shouldn't know what goes on inside the methods of ClsMain. That way if the internals of that class change, your program will still work.

因此,为了使您的程序能够预订活动,请 ClsMain 必须有这样的事件。它怎么知道什么时候发起活动?当创建 ClsSub 的实例时,它可以预订其事件。当该类引发一个事件时, ClsMain 依次引发一个自己的事件。

So in order for your program to be able to subscribe to the event, ClsMain has to have such an event. How does it know when to raise the event? When it creates an instance of ClsSub, it could subscribe to its event. When that class raises an event, ClsMain, in turn, raises an event of its own.

public class ClsMain
{
    public event LogHandler OnDataRetrieved;

    public void ReadData()
    {
        ClsSub sub = new ClsSub();
        sub.OnDataRetrieved += OnDataRetrieved;
        sub.LoadData();
    }
}

现在,所有程序都知道 ClsMain 正在引发一个事件。它不知道也不关心 ClsMain 在内部如何决定引发该事件。所有它都知道它是 ClsMain 的公共接口,而不是它在内部的工作方式。 ClsMain 是业务,要知道它创建了 ClsSub ,订阅其事件,并通过引发事件进行响应

Now all your program knows is that ClsMain is raising an event. It doesn't know or care how ClsMain internally decides to raise that event. All it knows it the public interface of ClsMain, not how it works internally. It's the business of ClsMain to know that it creates a ClsSub, subscribes to its event, and responds by raising an event of its own.

(我不讨论事件是否是我在这种情况下要使用的东西-我假设您只是在尝试事件。)

(I'm not addressing whether or not events are what I'd use in this scenario - I'm assuming that you're just experimenting with events.)

这是我使用过的代码的编辑版本。我只是对其进行了足够的调整,以使其能够编译和运行。 OP中的代码没有 GetData 方法,因此我添加了一个返回一些伪数据的方法。

Here's the edited version of the code that I worked with. I just tweaked it enough for it to compile and run. The code in the OP didn't have a GetData method so I added one that returns some dummy data.

public class Data
{
    public string ID { get; set; }
    public string Description { get; set; }
}

public delegate void LogHandler(Data log);

public class ClsSub
{
    public event LogHandler OnDataRetrieved;

    public void LoadData()
    {
        DataTable dt = GetData();

        foreach (DataRow row in dt.Rows)
        {
            Data logdata = new Data();
            logdata.ID = row["UserID"].ToString();
            logdata.Description = row["Description"].ToString();

            if (OnDataRetrieved != null)
            {
                OnDataRetrieved(logdata);
            }
        }
    }

    private DataTable GetData()
    {
        var result = new DataTable();
        result.Columns.Add("UserID", typeof(string));
        result.Columns.Add("Description", typeof(string));
        result.Rows.Add("user1", "description1");
        result.Rows.Add("user2", "description2");
        return result;
    }
}

public class ClsMain
{
    public event LogHandler OnDataRetrieved;

    public void ReadData()
    {
        ClsSub sub = new ClsSub();
        sub.OnDataRetrieved += OnDataRetrieved;
        sub.LoadData();
    }
}

public class Program
{

    static void Main(string[] args)
    {
        ClsMain main = new ClsMain();
        main.OnDataRetrieved += ClsApplication_OnDataRetrieved;
        main.ReadData();
        Console.ReadKey();
    }

    private static void ClsApplication_OnDataRetrieved(Data log)
    {
        Console.WriteLine(log.ID + " " + log.Description);
    }
}

输出为


user1 description1

user2 description2

user1 description1
user2 description2

这篇关于如何使用委托跨类触发事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆