2012-02-23 3 views
4

ОК, я надеюсь, что название этого вопроса имеет смысл. В моем приложении у меня есть некоторые методы, которые должны быть вызваны специальным InvokeMethod. На данный момент, это работает так:Лучшая (общая) декларация делегатов Func

internal bool RemoteLogin(string password) 
{ 
    return (bool)InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password);    
} 

internal string GetSessionId() 
{    
    return (string)InvokeMethod(new Func<string>(Server.GetSessionId));      
} 

public object InvokeMethod(Delegate method, params object[] args) 
{ 
    return method.DynamicInvoke(args); 
}  

Для вызова InvokeMethod я должен пройти новый Func < ....>, добавьте параметр (ы), а также, возвращаемое значение соответствующего типа. Есть ли лучший (более общий) способ сделать это, например, используя Generics или Reflection?

Любая помощь очень ценится.

+2

Почему бы вам просто не вызвать методы напрямую? Зачем вообще использовать Delegate.DynamicInvoke? –

+2

В моем примере выше метод InvokeMethod упрощен. В моем приложении он выполняет журнал, мониторинг, обработку исключений и т. Д. Вызова. – Mike

ответ

3

Вы можете добиться определенного количества сильного ввода - за счет повторения с использованием Func вариантов:

public R InvokeMethod<T,R>(Func<T,R> method, T argument) 
{ 
    return method(argument); 
} 

public R InvokeMethod<T1,T2,R>(Func<T1,T2,R> method, T1 argument1, T2 argument2) 
{ 
    return method(argument1, argument2); 
} 

public R InvokeMethod<T1,T2,T3,R>(Func<T1,T2,T3,R> method, T1 argument1, T2 argument2, T3 argument3) 
{ 
    return method(argument1, argument2, argument3); 
} 

И так далее.

Хотя это соответствует вашему оригиналу, нет никакой реальной необходимости обрабатывать параметры вообще. Попробуйте написать ваш InvokeMethod этот путь:

public R InvokeMethod<R>(Func<R> method) 
{ 
    return method(); 
} 

, а затем вызвать его с этим стилем:

internal bool RemoteLogin(string password) 
{ 
    return InvokeMethod(() => Server.RemoteLogin(password)); 
} 

internal string GetSessionId() 
{    
    return InvokeMethod(() => Server.GetSessionId()); 
} 

Таким образом, оставить параметр обработки для лямбда-выражения, и вам нужно только написать InvokeMethod один раз.

+1

Вот что я искал! Большое спасибо за ваш ответ. Также большое спасибо всем, кто ответил. – Mike

1

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

public static T InvokeMethod<T>(Delegate method, params object[] args) 
{ 
    return (T)method.DynamicInvoke(args); 
} 

Тогда ваш вызов выше становится просто:

return InvokeMethod(new Func<string, bool>(Server.RemoteLogin), password); 

И тип Boolean возврата выводится по типу возвращаемого на ваш метод.

2

«В моем примере выше метод InvokeMethod упрощен. В моем приложении он выполняет журнал, мониторинг, обработку исключений и т. Д. Вызова».

Учитывая этот комментарий, мое предложение состоит в том, чтобы переделать это. Вместо вызова делегата, как это, вы могли бы сделать операцию взять Func<T>, например, так:

public T InvokeMethod<T>(Func<T> method) 
{ 
    // Add wrapper as needed 
    return method(); 
} 

Вы можете затем вызвать его с помощью лямбды, когда вам нужно передать параметры:

internal bool RemoteLogin(string password) 
{ 
    return InvokeMethod(() => Server.RemoteLogin(password));    
} 

internal string GetSessionId() 
{    
    return InvokeMethod(Server.GetSessionId);      
} 
1
static T Invoke<T>(Func<T> method) 
{ 
    //Log here 
    return method(); 
} 

bool RemoteLogin(string password) 
{ 
    return Invoke(() => Server.RemoteLogin(password)); 
} 
1

Дополнительная информация: Если метод не имеет возвращаемого значения (например, «void Logout()»), вы можете использовать делегат Action (метод может иметь указанное имя -> InvokeMethod -> из-за различной сигнатуры/параметра):

public void InvokeMethod(Action method) 
{ 
    method(); 
} 
Смежные вопросы