2017-01-26 2 views
1

я следующее:крепления обработчик, который возвращает значение к событию, C#

public String AttachService(string whereClauseParam) 
    { 
     //Get Client object here 
     Client c = new Client(); 
     string cookieFromRequest = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Cookie]; 
     tokenInfo.TryGetValue(cookieFromRequest, out c); 
     string[] arr = new string[] { }; 
     c.AttachedServiceStatus += OnAttachedServiceStatus; 
     string whereClause = whereClauseParam.ToString(); 
     //c.AttachService("binding.interface='query_em'", 8799989); 

     return string.Format("attached"); 
    } 

// Обработчик ниже код:

public string OnAttachedServiceStatus(Client sender, ClientServiceAttachedStatus status) 
    { 
     if (status.AttachStatus == AttachedStatus.Connected && status.ServiceAttachStatus == ServiceAttachStatus.Attached) 
     { 
      //update the Client object in Dictionary 
      Client c = new Client(); 

      var ou = tokenInfo.First(x => x.Value == sender); 
      tokenInfo.TryGetValue(ou.Key.ToString(), out c); 
      tokenInfo.TryRemove(ou.Key.ToString(), out c); 
      tokenInfo.TryAdd(ou.Key.ToString(), sender); 

      string[] statusInfoT = new string[200]; 
      statusInfoT[0] = status.ServiceId.ToString(); 
      statusInfoT[1] = status.AttachStatus.ToString(); 
      statusInfoT[2] = status.ServiceAttachStatus.ToString(); 
      statusInfoT[3] = status.VirtualServiceId.ToString(); 
      statusInfoT[4] = status.AttachToken.ToString(); 
      statusInfo.TryAdd(ou.Key.ToString(), statusInfoT); 

      //update the UI with a Dispatch - TO BE DONE 

     } 

     return "Connected"; 
    } 

Описанный выше метод AttachService имеет обработчик «OnAttachedServiceStatus» прикреплен к событие «AttachedServiceStatus». Пока функция OnAttachedServiceStatus возвращает void, все работает хорошо. Тем не менее, теперь мне нужно, чтобы Handler OnAttachedServiceStatus возвращал строку, но я не могу правильно прикрепить обработчик.

Я думаю об использовании делегата Func, но не знаю, как его использовать. Пожалуйста, помогите!

+2

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

+0

Я хочу, чтобы обработчик «OnAttachedServiceStatus» возвращал строку обратно Caller «AttachService», но я не могу получить следующие правильные – RookieDude

+0

c.AttachedServiceStatus + = OnAttachedServiceStatus; – RookieDude

ответ

1

Прежде всего, подпись обработчика события определяется типом делегата события. Если этот делегат возвращает void, то вы не можете приложить другие методы. Оба параметра метода и возвращаемого значения должны соответствовать сигнатуре делегата even. Я считаю, что AttachedServiceStatus использует делегат, который возвращает void. Нечто подобное:

public delegate void Action<T1, T2>(T1 arg1, T2 arg2) 

И событие

public event Action<Client, ClientServiceAttachedStatus> AttachedServiceStatus 

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

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2) 

Вы можете объявить событие как

public event Func<Client, ClientServiceAttachedStatus> AttachedServiceStatus 

Но это не имеет никакого смысла. Потому что событие является делегатом. Когда вы присоединяете обработчик, вы фактически объединяете делегатов, создавая что-то вроде списка делегатов (список вызовов). Этот список содержит все прикрепленные обработчики. Когда вы поднимаете событие, все обработчики в списке вызовов вызывается один за другим, и возвращается только результат последнего вызванного обработчика. Заказ invokation не определен. Таким образом, вы даже не знаете, какой обработчик вернул значение.

(*) Хотя все же можно получить все результаты, если вы будете вызывать каждый обработчик вручную, а не поднимать событие. См Servy комментарий ниже


UPDATE

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

When вы прикрепляете обработчик к событию, обработчик не выполняется. Он просто добавлен в список вызовов. Обработчик события будет выполнен, когда Client будет raise event. Таким образом, AttachService здесь не является. Client является вызывающим. И вы не можете вернуть строку обратно до AttachService. После присоединения обработчика к событию код выйдет из метода AttachService. Некоторое время спустя событие будет поднято, и обработчик будет выполнен, но он не будет связан с методом AttachService.

+0

Хотя поведение * default * действительно просто дает вам случайное значение, вы не можете использовать обработчики добавления/удаления по умолчанию, или просто не вызывайте 'Invoke' для вызова обработчиков, а вместо этого разбивайте их и вызываете их отдельно. Это очень нетипично и вряд ли подходит для большинства ситуаций, но это не * невозможно *. Все, что говорило, OP, похоже, не владеет классом, определяющим событие, в первую очередь, он пытается предоставить значение для кода, который привязывает обработчик, а не код, вызывающий событие, поэтому ни одно из этого не имеет к нему никакого отношения , – Servy

+0

@Servy хорошая точка в вызове ручных делегатов. Но что вы подразумеваете под *, он пытается обеспечить ценность кода, связанного с обработчиком *? Насколько я понимаю, он пытался подключить обработчик с неправильной подписью, что невозможно, как я сказал выше –

+0

http://stackoverflow.com/questions/41877040/attaching-handler-that-returns-a-value-to-an-event- c-sharp/41877212? noredirect = 1 # comment70936377_41877040 – Servy

0

Я не уверен, что вы понимаете, как работают события.

Client c = new Client(); 
    // ... 
    c.AttachedServiceStatus += OnAttachedServiceStatus; 

OnAttachedServiceStatus здесь не называется. Вместо этого это указывает объекту Client на вызов метода OnAttachedServiceStatus всякий раз, когда он вызывает событие AttachedServiceStatus, которое может произойти в любой момент в будущем. Это похоже на то, что вы рассказываете гонщику «Когда я говорю« идите », бегите так быстро, как можете, до финиша, а затем скажите мне, сколько шагов вам потребовалось, чтобы добраться туда». Гонщик сразу не начинает бегать в этом месте, и они не сообщают вам, сколько шагов он предпринял; они попадают в готовую позицию и ждут. Когда вы говорите «идти», это когда они выполняют ваши инструкции и начинают работать. К тому времени, как вы получите ответ, это хорошо после того, как вы дали ему инструкцию ждать.

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

стороны клиента:

public String ConnectToServer(string whereClauseParam) 
{ 
    //Create Server object here 
    Server s = new Server(); 
    s.AttachedServiceStatus += OnAttachedServiceStatus; 
    s.AttachService(this, whereClauseParam, 8799989); 
} 


public void OnAttachedServiceStatus (object sender, ClientServiceAttachedEventArgs e) 
{ 
    if (e.AttachStatus == AttachedStatus.Connected && e.ServiceAttachStatus == ServiceAttachStatus.Attached) 
    { 
     // Update the UI with the message from the server. 
     MessageBox.Show(e.Message); 

     // If you need to do something else with the server in response, you can do this: 
     ((Server)sender).Foo("bar"); 
    } 
} 

и на стороне сервера, определить класс пользовательских EventArgs для Вашего мероприятия:

// By making this inherit from EventArgs, we can use the built-in EventHandler<T> delegate for the event itself. 
public class ClientServiceAttachedEventArgs : EventArgs 
{ 
    public AttachedStatus AttachStatus { get; set; } 
    public ServiceAttachStatus ServiceAttachStatus { get; set; } 
    public string Message { get; set; } 
    // You can put in as many properties as you want to carry the information back from the server. 
} 

и поставьте это в вашем классе сервера:

public event EventHandler<ClientServiceAttachedEventArgs> AttachedServiceStatus; 

public String AttachService(Client client, string whereClauseParam, int code) 
{ 
    // Do what you need to do to register the client. 
    //... 

    // Assuming everything went as planned, fire the event. 
    // First, construct the EventArgs with information about the results of the connection. 
    ClientServiceAttachedEventArgs e = new ClientServiceAttachedEventArgs(); 
    e.AttachStatus = AttachedStatus.Connected; 
    e.ServiceAttachStatus = ServiceAttachStatus.Attached; 
    e.Message = "Attached"; 

    // This is where your OnAttachedServiceStatus method in the client finally gets called. If the event handler were returning a string, this is where it would be returned to and I can't imagine this does you any good. 
    AttachedServiceStatus(this, e); 
} 

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

Смежные вопросы