How to trigger an event across classes using delegates?

橙三吉。 提交于 2019-12-13 04:10:19

问题


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


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


回答1:


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

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

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.

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

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.)


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

The output is

user1 description1
user2 description2



来源:https://stackoverflow.com/questions/55497377/how-to-trigger-an-event-across-classes-using-delegates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!