В C # 3.5, как вы передаете, какой метод для вызова объекта в качестве параметра - PullRequest
5 голосов
/ 22 июня 2009

У меня есть два метода в C # 3.5, которые одинаковы для одного вызова функции, в приведенном ниже фрагменте см. clientController.GetClientUsername против clientController.GetClientGraphicalUsername

    private static bool TryGetLogonUserIdByUsername(IGetClientUsername clientController, string sClientId, out int? logonUserId)
    {
        string username;
        if (clientController.GetClientUsername(sClientId, out username))
        {
           // ... snip common code ...
        }

        return false;
    }

    private static bool TryGetLogonUserIdByGraphicalUsername(IGetClientUsername clientController, string sClientId, out int? logonUserId)
    {
        string username;
        if (clientController.GetClientGraphicalUsername(sClientId, out username))
        {
           // ... snip common code ...
        }

        return false;
    }

Есть ли способ (делегаты, лямды?), Который я могу передать, какой метод на clientController я хочу вызвать?

Спасибо!

Ответы [ 5 ]

9 голосов
/ 22 июня 2009

Хотя вы можете передать делегата в качестве параметра, я предлагаю пойти по другому маршруту. Инкапсулируйте тело оператора if, включающего общий код в другую функцию, и вызывайте его в обеих функциях.

Visual Studio имеет функцию «Refactor -> Извлечь метод» в контекстном меню. Вы можете просто заполнить одно из тел, выбрать тело и использовать эту функцию для автоматического извлечения из него метода.

7 голосов
/ 22 июня 2009

Конечно. Просто определите делегата так:

public delegate bool GetUsername(string clientID, out string username);

А затем передайте его в свою функцию и вызовите:

private static bool TryGetLogonUserId(IGetClientUsername clientController, string sClientId, out int? logonUserId, GetUsername func)
{
    string username;
    if (func.Invoke(sClientId, out username))
    {
       // ... snip common code ...
    }
    return false;
}

Чтобы вызвать функцию с делегатом, вы сделаете это:

TryGetLogonUserId(/* first params... */, clientController.GetClientUsername);
1 голос
/ 22 июня 2009

Тип функции записывается как Func . Я не уверен, что параметры «out» правильно передаются в типах «Func», но вы должны сделать свою функцию похожей на

void TryGetLogon(Func<IGetClientUsername, string, out int?, bool> f) { 
   // ...
   f(x, y, z, a);
}
// ...
TryGetLogon(TryGetLogonUserIdByGraphicalUsername);
0 голосов
/ 22 июня 2009

Как насчет просто передать логический флаг?

private static bool TryGetLogonUserIdByUsername(
    IGetClientUsername clientController,
    string sClientId, out int? logonUserId, bool graphical)
{
    string username;
    bool gotClient = false;

    if (graphical)
    {
        gotClient = clientController.GetClientGraphicalUsername(
            sClientId, out username);
    }
    else
    {
        gotClient = clientController.GetClientUsername(
            sClientId, out username);
    }

    if (gotClient)
    {
               // ... snip common code ...
    }

    return false;
}
0 голосов
/ 22 июня 2009

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

private static readonly MethodInfo getRegularLogin = typeof(IGetClientUsername).GetMethod("GetClientUsername");
private static bool TryGetLogonUserIdByUsername(IGetClientUsername clientController, string sClientId, out int? logonUserId)
{

    string username;
    return TryGetLoginReflective(getRegularLogin, clientController, sClientId, out username, out logonUserId);
}

private static readonly MethodInfo getGraphicalLogin = typeof(IGetClientUsername).GetMethod("GetClientGraphicalUsername");
private static bool TryGetLogonUserIdByGraphicalUsername(IGetClientUsername clientController, string sClientId, out int? logonUserId)
{
    string username;
    return TryGetLoginReflective(getGraphicalLogin,  clientController, sClientId, out username, out logonUserId);
}

private static bool TryGetLoginReflective(MethodInfo method, IGetClientUsername clientController, string sClientId, out string username, out int? logonUserId)
{
    object[] args = new object[]{sClientId, null};
    if((bool)method.Invoke(clientController, args))
    {
         // ... snip common code ...
    }
    logonUserId = ...;

    username = (string)args[1];
    return false;
}
...