0

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?

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
Michael
  • 43
  • 6
  • Is there any way to do this? – Michael Apr 03 '19 at 15:29
  • https://stackoverflow.com/questions/2082615/pass-method-as-parameter-using-c-sharp You could try passing a Func delegate from one class to the other. – Dortimer Apr 03 '19 at 16:16
  • The code you posted doesn't compile - stuff like `Public` vs. `public`. I had to edit the code a lot to get it to compile so that I could work on an answer. It's a good idea to post code that's complete enough that someone can copy and paste it directly so that they can work with it. – Scott Hannen Apr 03 '19 at 16:45

1 Answers1

0

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

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • I have done this.But in the foreach() after first loop,checks the 1 st row and it raises an event.It doesn't loop to other rows.Then after 1 st loop,it again check the 1 st row.It doesn't checking the remaining rows.How it is done – Michael Apr 03 '19 at 17:05
  • I actually need,i got a lot of data and return as DataTable GetData(). Then i need to sort it with some conditions in the for each statement.After extracting datas with some conditions and need to be raise that result to an event.In the above code only 1 time looping is done.after that it raises an even.I am using a timer function for periodically checking the data an store it in the datatable. – Michael Apr 03 '19 at 17:21
  • foreach (DataRow row in dt.Rows) { logdata.ID = row["UserID"].ToString(); logdata.Description = row["Description"].ToString(); if (OnDataRetrieved != null) { OnDataRetrieved(logdata); } } – Michael Apr 03 '19 at 17:22
  • That sounds like it might be a different question. It sounds like you're asking about something other than raising and subscribing to events. If so, it's better to ask the other part in a different question. – Scott Hannen Apr 03 '19 at 17:32
  • Any idea of doing this? – Michael Apr 03 '19 at 17:33
  • I am actually needed the above one.But it is not working when we have multiple datas in the data table – Michael Apr 03 '19 at 17:35
  • I actually have 48 records in the datatable.So datas are extracted mainly in the for each statement and I am writing different conditions for extraction..So while first loop,checks the data row and meet the condition that i wrote and raises an event and it will publish it to the subscriber as per the code.Then the next record should be checked.But it seems not checking the next row in the datatable.Looping should not be completed.Only checked the 1 st row.What to be done for this? – Michael Apr 03 '19 at 17:42
  • I actually have 48 records in the datatable.So datas are extracted mainly in the for each statement and I am writing different conditions for extraction..So while first loop,checks the data row and meet the condition that i wrote and raises an event and it will publish it to the subscriber as per the code.Then the next record should be checked.But it seems not checking the next row in the datatable.Looping did not completed.Only checked the 1 st row.What to be done for this? – Michael Apr 03 '19 at 17:51
  • In the example code I posted, the DataSet has two rows, and the output indicates that the event is raised for both. Perhaps one approach would be to start from the code I posted and then replace my fake `GetData` method with your real one. It's definitely looping through the rows and raising an event for each one. – Scott Hannen Apr 03 '19 at 18:06
  • 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); } } – Michael Apr 03 '19 at 18:32