Как вызвать событие между классами с помощью делегатов? - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть 2 разных класса, и мне нужно подписать событие в методе main. Но я не получаю подписку на событие в методе main. Кто-нибудь знает, как это сделать?

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, на метод main. Как скрыть это событие в методе main?

1 Ответ

0 голосов
/ 03 апреля 2019

Это может ответить на ваш вопрос:

Класс не может подписаться на событие в другом классе, о котором он не знает.Класс также не может подписаться на событие, которое не существует.

Main создает новый экземпляр ClsMain, а затем пытается подписаться на его OnDataRetrieved событие.

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

Первоначальная проблема заключается в том, что ClsMain не имеет ни одного такого события, поэтому на него невозможно подписаться.

ClsSub действительно имеет такое событие.Но ваше приложение не использует экземпляр ClsSub.Он использует ClsMain.Он не знает, что ClsMain создает экземпляр ClsSub, и это хорошо.Он не должен знать, что происходит внутри методов ClsMain.Таким образом, если внутренние компоненты этого класса изменятся, ваша программа все равно будет работать.

Таким образом, чтобы ваша программа могла подписаться на событие, ClsMain должно иметь такое событие.Как он узнает, когда нужно поднять событие?Когда он создает экземпляр ClsSub, он может подписаться на свое событие.Когда этот класс вызывает событие, ClsMain, в свою очередь, вызывает собственное событие.

public class ClsMain
{
    public event LogHandler OnDataRetrieved;

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

Теперь все, что ваша программа знает, это то, что ClsMain вызывает событие.Он не знает и не заботится о том, как ClsMain внутренне решает поднять это событие.Все это знает общедоступный интерфейс ClsMain, а не то, как он работает внутри.Задача ClsMain состоит в том, чтобы знать, что он создает ClsSub, подписывается на свое событие и отвечает, вызывая собственное событие.

(Я не рассматриваю, являются ли события тем,Я бы использовал в этом сценарии - я предполагаю, что вы просто экспериментируете с событиями.)


Вот отредактированная версия кода, с которым я работал.Я просто настроил его достаточно, чтобы он скомпилировал и запустил.В коде в OP не было метода GetData, поэтому я добавил метод, который возвращает фиктивные данные.

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

...