События, возвращающие значения как методы, это правильно? - PullRequest
4 голосов
/ 24 июля 2010

В моем приложении я хотел, чтобы класс B получил некоторую информацию от класса A, но, поскольку A создает экземпляры B, B не имеет ссылки на A (намеренно). Я никогда не использовал события для этой цели, поэтому я не уверен, правильно ли это, но это работает:

class A
{
 public delegate bool GetFromB();
 public event GetFromB GetDataFromB;
...

//get data from B without having an access to it
bool Result=GetDataFromB();
}

class B
{
A a=new A();
A.GetDataFromB=new A.GetFromB(DO_THAT);

public bool DO_THAT()
{
 ...
return true;     //and that is it, it will return to event caller
}

}

Ответы [ 3 ]

2 голосов
/ 24 июля 2010

Это, безусловно, будет работать, и этот подход используется в нескольких местах в базовой структуре - AssemblyResolve и т. Д. Альтернативные подходы здесь:

  • , если он используется методом , передать его в метод в качестве делегата обратного вызова. Тот же подход , но просто не выставленный как event
  • То же самое, но с интерфейсом

но так будет работать. Это не неслыханно. Код подправляется, хотя:

A a=new A();
a.GetDataFromB=+new A.GetFromB(DO_THAT);

вы подписаны на экземпляр (если он не статический), и вам нужно +=, а не =.

Также: рассмотрите возможность использования Func<bool> вместо объявления собственного типа делегата.

1 голос
/ 24 июля 2010

Не делай этого.События подразумевают, что можно использовать несколько слушателей, и похоже, что вы не обрабатываете возвращаемые значения от нескольких слушателей.Вы можете сделать это, пройдя myevent.GetInvocationList () и вызывая каждого слушателя отдельно.

Вместо этого используйте простой делегат:

class A
{
   public delegate bool GetFromB();
   public GetFromB GetDataFromB { get; set; }
}

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

class MyEventArgs : EventArgs
{
   public bool ReturnValue {get; set; }
   // and something more here.
}

public class A
{
   public event EventHandler<MyEventArgs> MyEvent;
}
0 голосов
/ 24 июля 2010

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

Если B требуется несколько различных данных из A, вы можете позволить A реализовать некоторый IBNeededData интерфейс. Если B нужен только один вызов для A, прямым решением будет метод обратного вызова.

Редактировать

Вот пример для обратного вызова. (Надеюсь, что вы в порядке с лямбда-выражением, чтобы предоставить данные из А.)

   [TestClass]
   public class UnitTest1 {
      class A {
         public void DoWork() {
            B b = new B();

            //b.GetData = () => "Some data";
            Func<string> callback = new Func<string>(this.GetBData);
            b.GetData = callback;

            b.DoBWork();
         }
         private string GetBData() {
            return "Some data";
         }
      }
      class B {
         public Func<string> GetData { get; set; }
         public void DoBWork() {
            string data = GetData();
            Console.WriteLine("Working with {0}", data);
         }
      }

      [TestMethod]
      public void TestMethod1() {
         A a = new A();
         a.DoWork();
      }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...