I'm currently learning F# by re-doing a simple mobile application I did in C# and Xamarin.forms which has forgoal to connect a user with facebook and get his profile and posts.
I almost finish everything but I'm blocked. To do my connection to the facebook API in C#, I used the Xamarin.Auth library and I want to reuse this library in F#.
Here is my code for my LoginPage ViewModel in C#:
public class LoginPageViewModel : BaseViewModel
{
private readonly INavigationService _navigationService;
private readonly IConfiguration _config;
private LoginLogic _loginLogic;
public ICommand NavigateCommand { get; set; }
public OAuth2Authenticator MyAuthenticator;
public ICommand ConnectVerification { get; set; }
public bool CanSkipPage { get; set; }
public LoginPageViewModel(INavigationService navigationService, IConfiguration configuration)
{
if (navigationService == null) throw new ArgumentNullException("navigationService");
_navigationService = navigationService;
if (configuration == null) throw new ArgumentNullException("Configuration");
_config = configuration;
NavigateCommand = new RelayCommand(() => { _navigationService.NavigateTo(Locator.FacebookProfilePage); });
MyAuthenticator = new OAuth2Authenticator(
_config.facebookAppId,
_config.scope,
new Uri(_config.facebookAuthUrl),
new Uri(_config.facebookRedirectUrl),
null);
MyAuthenticator.Completed += OnAuthenticationCompleted;
MyAuthenticator.Error += OnAuthenticationFailed;
_loginLogic = SimpleIoc.Default.GetInstance<LoginLogic>();
this.ConnectVerification = new AsyncCommand(() => TokenVerification());
}
public async Task TokenVerification()
{
IsLoading = true;
if (await _loginLogic.CheckToken())
NavigateCommand.Execute(null);
IsLoading = false;
}
async void OnAuthenticationCompleted(object sender, AuthenticatorCompletedEventArgs e)
{
IsLoading = true;
var authenticator = sender as OAuth2Authenticator;
if (authenticator != null)
{
authenticator.Completed -= OnAuthenticationCompleted;
authenticator.Error -= OnAuthenticationFailed;
}
await _loginLogic.SetTokenAsync(e.Account.Properties["access_token"]);
loginLogic.SetTokenAsync(e.Account.Properties["access_token"]);
NavigateCommand.Execute(null);
IsLoading = false;
}
void OnAuthenticationFailed(object sender, AuthenticatorErrorEventArgs e)
{
var authenticator = sender as OAuth2Authenticator;
if (authenticator != null)
{
authenticator.Completed -= OnAuthenticationCompleted;
authenticator.Error -= OnAuthenticationFailed;
}
}
}
My problem is to use Xamarin.Auth. I have to create a OAuth2Authenticator property that I initialize in the constructor of my class and then subscribe both EventHandler.Complete and.Error of this property to the two events OnAuthenticationCompleted and OnAuthenticationFailed in my class constructor and I've no idea how to do that in F#. Right now, my F# class looks like this:
open Xamarin.Auth
open System
open GalaSoft.MvvmLight.Views
type LoginPageViewModel(navigationService: INavigationService) =
inherit ViewModelBase()
let mutable isLoading = false
let authenticator = new OAuth2Authenticator(config.facebookAppId,
config.scope,
new Uri(config.facebookAuthUrl),
new Uri(config.facebookRedirectUrl),
null)
member this.MyAuthenticator
with get() = authenticator
member this.IsLoading
with get() = isLoading
and set(value) =
isLoading <- value
base.NotifyPropertyChanged(<@ this.IsLoading @>)
member this.TokenVerification() =
this.IsLoading <- true
if loginLogic.CheckToken()
then
navigationService.NavigateTo("FacebookProfilePage")
this.IsLoading <- false
But I don't know:
First, Where I should create my two methods OnAuthenticationCompleted and OnAuthenticationFailed, are they supposed to be methods of the class or not?
Second, How To subscribe my OAuth2Authenticator.Complete to OnAuthenticationCompleted and OAuth2Authenticator.Error to OnAuthenticationFailed methods in my class constructor
You can add even handlers to your authenticator object using the following syntax:
let auth = OAuth2Authenticator("clientId", "scope", Uri("??"), Uri("??"))
auth.Error.Add(fun err ->
printfn "Error: %A" err)
auth.Completed.Add(fun res ->
let at = res.Account.Properties.["access_token"]
printfn "%A" at)
If you want to be able to add and remove the handler, then you need to create an explicit EventHandler
value first:
let auth = OAuth2Authenticator("clientId", "scope", Uri("??"), Uri("??"))
let handler = EventHandler<AuthenticatorCompletedEventArgs>(fun _ res ->
let at = res.Account.Properties.["access_token"]
printfn "%A" at)
auth.Completed.AddHandler(handler)
auth.Completed.RemoveHandler(handler)
That said, if you simply translate the C# code to F#, then you probably won't gain much in this case. Your logic is quite imperative and things like the mutable isLoading
field and adding/removing of event handlers is going to make your F# code quite ugly. If you want to develop mobile applications with F#, then I would instead recommend looking at Fabulous , which lets you write nice functional code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.