Использование Func‹T,TResult› С#

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

Текущий случай:

У меня есть простые методы, которые принимают параметры и предоставляют GPlus, Facebook или Simple logIn с именем пользователя и паролем. как в коде ниже:

public async Task<SignInResponse> SignInUsingFacebook(IFacebookInitializer faceBookConfiguration)
{
   //my code
}
public async Task<SignInResponse> SignInUserNameAndPass(string username,string password)
{
   //my code
}
public async Task<SignInResponse> SignInUsingGPlus(IGPlusInitializer gPlusConfiguration)
{
   //my code
}

Это здорово, я могу вызывать их напрямую из своего приложения и обрабатывать данные, но недавно я столкнулся с Delegates и Func<T,TResult>.

Что я хочу сделать:

Мне нужен простой метод, который принимает в качестве параметра перечисление LogInType, как показано ниже:

public enum LogInType
{
    UserNameAndPassword,
    Facebook,
    GooglePlus,
}

и в зависимости от типа входа в систему, предоставленного методу, самостоятельно обрабатывает процесс входа в систему и просто возвращает объект SignInResponse.


Есть ли способ сделать это с помощью делегатов. Вместо того, чтобы иметь 3 отдельных метода для вызова для каждого случая. Если да, то может кто-нибудь помочь с параметрами, которые будут переданы методу Single вместе с LogInType. Я знаю, что это должен быть Func, но как будет выглядеть Func, поскольку он должен принимать 3 разных параметра.


Из комментариев:

Каждый из этих методов в любом случае представляет собой другую сигнатуру, поэтому у вас есть Func<IFacebookInitializer, Task<SignInResponse>>, Func<string, string, Task<SignInResponse>> и Func<IGPlusInitializer, Task<SignInResponse>>, поэтому вы все равно получите оператор if.

Могу ли я вернуть Func при вызове метода? Таким образом, я могу вернуть любую из трех функций на основе случая быстрого переключения. Проблема будет заключаться (если это возможно) в том, что будет типом общего ответа (или общего ответа) метода, который возвращает любой из этих трех методов.


person iam.Carrot    schedule 26.04.2017    source источник
comment
Вместо того, чтобы передавать перечисление и пытаться получить параметры в методе, почему бы не создать абстрактный класс Parameters и создать его подкласс для каждого из трех вариантов входа в систему?   -  person Kempeth    schedule 26.04.2017
comment
Каждый из этих методов в любом случае представляет собой другую сигнатуру, поэтому у вас есть Func<IFacebookInitializer, Task<SignInResponse>>, Func<string, string, Task<SignInResponse>> и Func<IGPlusInitializer, Task<SignInResponse>>, поэтому вы все равно получите оператор if.   -  person DavidG    schedule 26.04.2017
comment
@Kempeth Я пробовал, просто это не имеет большого значения по сравнению с Func, когда я наткнулся на него.   -  person iam.Carrot    schedule 26.04.2017
comment
@DavidG Могу ли я вернуть Func при вызове метода? таким образом я могу вернуть любой из трех func на основе случая быстрого переключения. Проблема будет заключаться (если это возможно) в том, что будет типом общего ответа (или общего ответа) метода, который возвращает любой из этих трех методов.   -  person iam.Carrot    schedule 26.04.2017


Ответы (1)


Общий Func работает следующим образом: последний тип данных, который вы определяете в Func - "выход" в этом случае должен быть типом возвращаемого значения метода, который вы собираетесь использовать для этой конкретной функции, и этот метод также должен быть статическим. Это может помочь:

Func<LogInType, string> Login = LoginMethod;

private static string LoginMethod(LogInType loginType)
{
    if (loginType == LogInType.Facebook)
        return "Facebook";
    if (loginType == LogInType.GooglePlus)
        return "GooglePlus";
    if (loginType == LogInType.UserNameAndPassword)
        return "UserNameAndPassword";
    return "Default";
}

Тип возвращаемого значения в приведенном выше примере — строка просто для пояснения.

person Raviraj Palvankar    schedule 26.04.2017
comment
Как я должен передавать параметры? как имя пользователя или пароль или IFacebook или IGPlus? - person iam.Carrot; 26.04.2017
comment
Вы можете объявить общий родительский интерфейс (например, ILoginDetails) с именем пользователя и паролем. Наследуйте этот интерфейс для каждого из ваших интерфейсов и передайте его в качестве входных данных. Вы можете добавить n параметров в свою функцию: Func‹param1, param2, param3, param4, outputParam› - person Raviraj Palvankar; 26.04.2017
comment
Итак, Func‹ILogInInputParameters,SignInResponse› LogIn = LoginMethod, где ILogInInputParameters должно иметь свойство с именем LogInType? Это то, что ты имеешь в виду? а затем используйте is и проверьте три возможных сценария - person iam.Carrot; 26.04.2017
comment
Вы можете сделать это, если хотите, я бы предложил следующее: Func‹ILogInInputParameters, LogInType, SignInResponse› Лучше оставить LogInType как отдельный параметр, потому что параметры входа не имеют ничего общего с типом входа. - person Raviraj Palvankar; 26.04.2017
comment
Так что это будет просто пустой интерфейс - person iam.Carrot; 26.04.2017
comment
Почему это будет пустой интерфейс? он будет содержать свойства Username и Password; вы также можете добавить другие общие свойства, которые вы хотите использовать, я дал предложение для вашей проблемы, как разработать решение, зависит от вас. Спасибо! - person Raviraj Palvankar; 26.04.2017
comment
Обратите внимание: нет общих свойств. Имя пользователя и пароль требуются только для обычного входа в систему, а не для Facebook или GooglePlus. Для Facebook вы должны передать идентификатор приложения и идентификатор разработчика, тогда как для Google существует другой сценарий. - person iam.Carrot; 26.04.2017
comment
Затем вместо создания интерфейса для параметров создайте родительский класс LoginParameters с именем пользователя, паролем, IFacebookInitializer и IGPlusInitializer. Таким образом, нет наследования контракта, просто класс-оболочка для параметров. - person Raviraj Palvankar; 26.04.2017
comment
Может ли мой LogInMethod вместо этого вернуть Func? Подобно общедоступной функции Func‹T,TResult› FetchLogInMethod(LogInType TypeOfLogIn){} и может вызываться как var del = FetchLogInMethod(LogInType.Facebook); а затем запустите del как del(); - person iam.Carrot; 26.04.2017
comment
Он может возвращать Func как возвращаемый тип, но зачем все усложнять? Всего вам придется вернуть 3 разных функции. Делайте это как можно проще, это не будет иметь большого значения. - person Raviraj Palvankar; 26.04.2017
comment
Можете ли вы поделиться образцом для этого? Это будет большим подспорьем - person iam.Carrot; 26.04.2017
comment
Я думаю, вам следует просто написать один Func‹› или даже простой метод класса с типом возвращаемого значения, который вы хотите, LoginParameters и LogInType будут параметрами для этого метода и написать внутри него случай переключения на основе LogInType и выполнить соответственно, возврат Func без причины сделает все сложное ненужным. - person Raviraj Palvankar; 26.04.2017