Как заставить использовать подписаться на событие метода - PullRequest
1 голос
/ 24 декабря 2011

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

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

Возможно ли это вообще?Или комментариев HELP и XML достаточно, чтобы упомянуть пользователя, подписавшегося на событие.

Мой интерфейс выглядит так:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Robot.SkolaCa.BusinessObjects;

namespace Robot.SkolaCa.FiskalPrinter
{
    public delegate void OnRacunSuccessEvent(object sender, OnRacunSuccessArgs eargs);
    public delegate void OnRacunErrorEvent(object sender, OnRacunErrorArgs eargs);
    public class OnRacunErrorArgs : EventArgs
    {
        public string ErrorMessage { get; set; }
    }
    public class OnRacunSuccessArgs : EventArgs
    {   
        public string SuccesMessage { get; set; }
    }

    public interface IFiskalPrinter
    {
        bool PresjekStanja();
        bool DnevniIzvjestaj();
        /// <summary>
        /// PLEASE SUBSCRIBE TO ALL EVENTS !!!!
        /// </summary>
        /// <param name="racun"></param>
        void Racun(Racun racun);
        bool StornpRacuna(Racun racun, int brojFiskalnogKojiSeStornira);
        void SetConfig(IPrinterConfig config);
        event OnRacunSuccessEvent OnRacunSuccess;
        event OnRacunErrorEvent OnRacunError;
    }
}

Ответы [ 3 ]

3 голосов
/ 24 декабря 2011

События по определению являются факультативными, то есть, если кто-то хочет, он / она подписывается, если нет - тогда это его / ее право. Объявляя о событии, вы говорите: «Если кому-то интересно, я сообщу ему о каком-либо событии». Поэтому сама идея принудительного подписки неверна.

Но если вам нужно заставить потребителей что-то делать, вам лучше объявить соинтерфейс для ваших потребителей класса и заставить ваши методы получать реализации интерфейса в качестве аргументов. Например:

public interface IFiskalPrinterConsumer
{
    void OnRacunSuccess(string successMessage);
    void OnRacunError(string errorMessage);
}

public interface IFiskalPrinter
{
    bool PresjekStanja();
    bool DnevniIzvjestaj();
    void Racun(Racun racun, IFiskalPrinterConsumer consumer);
    bool StornpRacuna(Racun racun, int brojFiskalnogKojiSeStornira);
    void SetConfig(IPrinterConfig config);
}

Таким образом, вы сможете генерировать ошибки времени выполнения, если вызывающий абонент принимает значение NULL как consumer, и вызывающий не сможет не подписаться. Это сделает ваш контракт более понятным. Теперь вы говорите: «Я не пойду на работу, если вы не дадите мне объект слушателя».

Затем вы можете создать, скажем, правила Code Analysis или FxCop, чтобы проверить, что никто не реализует интерфейс с пустыми реализациями методов.

И так далее ...

Но шутка такова: если кто-то хочет нарушить ваши правила, он сделает это.

UPDATE

Решение для совместного интерфейса может быть даже лучше, потому что с event вы можете иметь не только 0 подписчиков, но и 1000 подписчиков. Как насчет написания комментариев XML со словами «пожалуйста, убедитесь, что у вас всегда есть ровно одна подписка»? Вы знаете, это довольно сложно проверить.

1 голос
/ 24 декабря 2011

Ну, вы можете как бы "заставить" пользователя подписаться на событие (если, например, это одно событие или небольшое количество, что должно быть подписано)

  1. Вы можете создать частный конструктор по умолчанию
  2. Вы можете создать один конструктор, который, подобно параметру (ам), принимает делегатов, которые вы добавляете в ваши события.
  3. Если пользователь вашего класса передает null вместо delegate, вы можете вызвать исключение, поэтому вы получите исключение времени выполнения и не время компиляции .

В этом случае у пользователя вашего класса не будет другого пути, кроме как просто передать делегат.Вид вашего типа архитектурного ограничения.

РЕДАКТИРОВАТЬ

Существует другое решение, imo, что может быть применено в этом случае, это использование Аспектно-ориентированного программирования (я никогда не делалэто для этой проблемы раньше, так что это просто советую тоже посмотреть).Если вы пометите свой класс атрибутом и во время компиляции ваш код проверки аспекта определит, что ни один делегат не был передан, может сгенерировать ошибку времени компиляции .

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

Надеюсь, это поможет.

0 голосов
/ 24 декабря 2011

Вы не можете форсировать это программно, то есть вы не можете вызвать ошибку компиляции. Если это был абстрактный класс, вы можете делать такие вещи, как переопределение Dispose или проверка вызывающих событий на наличие существующих ссылок или даже очистка ваших обработчиков, но для интерфейсов вы можете сделать очень мало.

...