Событийные классы в C # - PullRequest
3 голосов
/ 14 мая 2011

Я создаю управляемый событиями класс, чтобы при передаче ему серии данных он обрабатывался, а затем возвращал значение, когда был готов.

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

   public delegate void MyEventHandler(double result);

    public static MyEventHandler EventComplete;

    public static void MakeSomethingHappen(double[] data)
    {
        ThreadPool.QueueUserWorkItem(DoSomething, data);
    }
    private static void DoSomething(object dblData)
    {
        InvokeEventComplete(AndSomethingElse((double[])dblData));
    }

    private static void InvokeEventComplete(double result)
    {
        if (EventComplete != null)
        {
            EventComplete(result);
        }
    }

    public static double AndSomethingElse(double[] data)
    {
         //do some code
         return result; //double
    }

В моем основном классе я просто подключаю метод к событию следующим образом:

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);

Ответы [ 3 ]

3 голосов
/ 14 мая 2011

Вот вы:

  • Открытое событие как фактическое событие, а не общедоступный делегат участника.
  • Устранено дополнительное объявление делегата и использовано универсальное действие делегата.
  • Устранена дополнительная функция вызова, которая была просто многословна.
  • Использовано лямбда-выражение для регистрации события.

Отредактированный код:

MyClass.EventComplete += (result) => Console.WriteLine("Result is: " + result);

public class MyClass
{
    public static event Action<double> EventComplete;

    public static void MakeSomethingHappen(double[] data)
    {
        ThreadPool.QueueUserWorkItem(DoSomething, data);
    }

    private static void DoSomething(object dblData)
    {
        var result = AndSomethingElse((double[])dblData);

        if (EventComplete != null)
        {
            EventComplete(result);
        }
    }

    public static double AndSomethingElse(double[] data)
    {
        //do some code
        return result; //double
    }
}
1 голос
/ 14 мая 2011

Некоторые вещи, которые нужно учитывать ...

В .NET есть EventHandler<T> where T : EventArgs, но компромисс заключается в том, что вы в конечном итоге пишете пользовательские EventArgs для передачи ваших двойных данных вместо пользовательского делегата. Тем не менее, я думаю, что это более чистая модель.

Если бы вы определили ваше событие как

public static MyEventHandler EventComplete = delegate {};
//using a no-op handler like this has implications on Garbage Collection

Предотвращает ли GC использование лямбда-выражения no-op для инициализации события?

Вы можете сохранять каждый раз проверку if (EventComplete! = Null) и, следовательно, делать метод Invoke ... избыточным.

Вы также можете упростить

MyClass.EventComplete += new MyClass.EventCompleteHandler(MyClass_EventComplete);
to
MyClass.EventComplete += MyClass_EventComplete;

Кроме того, все выглядит хорошо. Я предполагаю, что все static вокруг кода только от работы в ConsoleApplication: -)

0 голосов
/ 14 мая 2011

попробуйте использовать стандартный шаблон событий (тысячи раз используются внутри FCL)

// in [CompleteEventArgs.cs] file
public class CompleteEventArgs : EventArgs {
    private readonly double _result;

    public CompleteEventArgs(double result) {
        _result = result;
    }

    public double Result {
        get { return _result; }
    }
}

// inside your class

// don't forget 'event' modifier(!) it prevents lots of illegal stuff
// like 'Complete = null' on the listener side
public static event EventHandler<CompleteEventArgs> Complete;

public static void MakeSomethingHappen(double[] data) {
    ThreadPool.QueueUserWorkItem(DoSomething, data);
}
private static void DoSomething(object dblData) {
    OnComplete(new CompleteEventArgs(AndSomethingElse((double[])dblData)));
}

// if you're working with a 'normal' (non-static) class
// here should be 'protected virtual' modifiers to allow inheritors
// use polymorphism to change the business logic
private static void OnComplete(CompleteEventArgs e) {
    if (Complete != null)
        Complete(null, e); // in 'normal' way here stands 'this' instead of 'null'
                           // this object (link to the sender) is pretty tricky
                           // and allows extra flexibility of the code on the listener side
}

public static double AndSomethingElse(double[] data) {
    double result = 0;
    //do some code
    return result; //double
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...