C # Внутренний делегат и публичное мероприятие - PullRequest
2 голосов
/ 10 декабря 2010

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

Согласно этой статье: http://msdn.microsoft.com/en-us/library/5z57dxz2.aspx (пример 2) нам нужно предоставить делегата для пользовательского события.

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

Спасибо за помощь.

Ответы [ 5 ]

6 голосов
/ 10 декабря 2010

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

Что ж, это не так.Только класс, который определяет это пользовательское событие, может вызвать его.Если это ваша проблема, не волнуйтесь.

4 голосов
/ 10 декабря 2010

Не верно.Не разрешается вызывать событие вне класса, которому принадлежит событие.Другие могут использовать только += и -= операторы для вашего мероприятия.Только в классе вы можете вызвать событие.В этом разница между событием и обычным делегатом.То есть:

public Data
{
   public event EventHandler OnSave
   public EventHandler OnLoad;

   private void Load()
   {
       if (OnLoad!=null) OnLoad();  
       //other operations
   }
   private void Save()
   {
       if (OnSave!=null) OnSave();  
       //other operations
   }
}

И вне класса:

Data data = new Data();
data.OnLoad += (s,e) => {}; 
data.OnSave += (s,e) => {};
data.OnLoad = (s,e)=>{}; 
//data.OnSave = (s,e)=>{};  //invalid
data.OnLoad();
//data.OnSave();  //invalid
2 голосов
/ 10 декабря 2010

Делегат - это просто объявление типа, описывающее «подпись» вашего события.Это должно быть публично.Чтобы фактически вызвать ваше событие, вы часто реализуете метод с именем OnEvent (где вы заменяете Event на Click или Closed или что-либо еще, описывающее ваше событие).Этот метод должен быть закрытым (или защищенным) в вашем классе.

Вы не можете объявить событие, используя делегат, который менее "видим", чем событие.

1 голос
/ 10 декабря 2010

Проблема в том, что любой может вызвать мой обработчик (и затем вызвать событие), даже в моем бизнес-коде

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

public event FooEventHandler Foo;

Единственное, что внешний код может сделать с событием, это подписаться на него (+=) или отказаться от него (-=). Он не может получить доступ к фактическому делегату, который генерируется компилятором как личное поле. Другими словами, этот код будет недействительным:

SomeClass x = new SomeClass();
x.Foo(x, new FooEventArgs()); // compilation error here

Не забывайте, что событие на самом деле представляет собой пару методов (добавление и удаление). Компилятор переписывает объявление события во что-то вроде этого:

private FooEventHandler _foo;

public event FooEventHandler Foo
{
    add { _foo += value; }
    remove { _foo -= value; }
}

(сгенерированный код на самом деле немного сложнее, с некоторой блокировкой для обеспечения безопасности потока)

Как видите, поле _foo является закрытым, поэтому клиентский код не может получить к нему доступ. Доступны только методы доступа add и remove.

1 голос
/ 10 декабря 2010

Один из способов сделать это:

Вместо публичного события создайте метод, который будет вручную подписывать желаемых делегатов и сохранять их в поле `private List _delegates '.

Затем,изнутри, звоните каждому из них, когда пожелаете.

public class Framework 
{
    public delegate void Method();
    public void AttachEvent(Method M)
    {
         _methods.Add(M);
    }
    private List<Method> _methods;
    private FireMethods() 
    {
         _methods.Foreach(x=>x.Invoke());
    }
}

Или вы можете использовать особую особенность событий, которые не доступны для общественности Invoke().

:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...