2014-02-17 4 views
-2

Так у меня есть следующие:Как сделать общий делегат EndInvoke?

private delegate Foo1 GetFooAsync1(Foo1 foo1); 
private delegate Foo2 GetFooAsync2(Foo2 foo2); 
private delegate Foo3 GetFooAsync3(Foo3 foo3); 
private delegate Foo4 GetFooAsync4(Foo4 foo4); 

private FooAsync1 foo1; 
private FooAsync2 foo2; 
private FooAsync3 foo3; 
private FooAsync4 foo4; 

А списки можно продолжать и дальше, то внутри метода я не хочу, чтобы положить попробовать поймать на каждом EndInvoke, потому что иногда он сгенерирует исключение, но это не должен останавливать систему и продолжать с другими Foos .. И занимает столько места в методе, если каждый из них попытался поймать его.

Есть ли общий способ для вызова end invoke? Итак, я могу вернуть ожидаемый результат?

var result1 = foo1.EndInvoke(fooIAsyncResult); 
+0

есть два biltin delegeates в .net Func и действие использовать это охватывающее 90 процентов сценария – Developerzzz

+0

вы можете передать лямбда-выражение http://stackoverflow.com/questions/14297633/c-sharp- pass-lambda-expression-as-method-parameter –

+0

Я не понимаю, почему вы пишете делегаты, которые принимают делегатов в качестве параметров. Я написал решение, которое не имеет такого гнездования. Если это не поможет, замените пример вашим фактическим кодом. –

ответ

0

Для достижения этой цели в общем виде, вы должны объявить метод расширения, который подменяет EndInvoke так:

public static class DelegateExtensions 
{ 
    public static TResult EndInvoke<TDelegate, TResult>(this TDelegate asyncCaller, IAsyncResult asyncResult) where TDelegate : System.Delegate 
    { 
     TResult result = default(TResult); 

     try 
     { 
      result = asyncCaller.EndInvoke(asyncResult); 
     } 
     catch (Exception ex) 
     { 
      LogExceptionMessageOrWhatever(ex.Message); 
      throw; 
     } 

     return result; 
    } 
} 

Однако эта процедура будет генерировать ошибку компилятора. Зачем? Класс System.Delegate - это специальный класс, который не может использоваться в общих ограничениях.

Так что вы не можете просто избавиться от ограничения и использовать отражение, чтобы вызвать правильную процедуру?

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

public delegate TFooResult GetFooAsync<TFooResult>(); 

public static class GetFooAsyncExtensions 
{ 
    public static TFooResult EndInvoke<TFooResult>(this GetFooAsync<TFooResult> asyncCaller, IAsyncResult asyncResult) 
    { 
     TFooResult result = default(TFooResult); 

     try 
     { 
      result = asyncCaller.EndInvoke(asyncResult); 
     } 
     catch (Exception ex) 
     { 
      LogExceptionMessageOrWhatever(ex.Message); 
      throw; 
     } 

     return result; 
    } 
} 

Теперь вы бы назвали EndInvoke, как обычно. Структура автоматически использует вашу версию.

private void Main() 
{ 
    Foo1Result foo1 = null; 

    var foo1Factory = new GetFooAsync<Foo1Result>(
     () => 
     { 
      return new Foo1Result(); 
     }); 


    foo1Factory.BeginInvoke(
     callback: asyncResult => 
      { 
       foo1 = foo1Factory.EndInvoke(asyncResult); 
      }, 
      @object: null); 
} 
Смежные вопросы