简体   繁体   English

F# class 构造函数中的事件

[英]F# Event in class constructor

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'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#. 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#:这是我在 C# 中的 LoginPage ViewModel 的代码:

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.我的问题是使用 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#.我必须创建一个 OAuth2Authenticator 属性,我在 class 的构造函数中初始化它,然后在我的 class 构造函数中将此属性的 EventHandler.Complete 和.Error 订阅到两个事件 OnAuthenticationCompleted 和 OnAuthenticationFailed ,我不知道该怎么做在 F# 中。 Right now, my F# class looks like this:现在,我的 F# class 看起来像这样:

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?首先,我应该在哪里创建我的两个方法 OnAuthenticationCompleted 和 OnAuthenticationFailed,它们是否应该是 class 的方法?

Second, How To subscribe my OAuth2Authenticator.Complete to OnAuthenticationCompleted and OAuth2Authenticator.Error to OnAuthenticationFailed methods in my class constructor其次,如何在我的 class 构造函数中订阅我的 OAuth2Authenticator.Complete 到 OnAuthenticationCompleted 和 OAuth2Authenticator.Error 到 OnAuthenticationFailed 方法

You can add even handlers to your authenticator object using the following syntax:您可以使用以下语法将偶数处理程序添加到您的身份验证器 object:

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:如果您希望能够添加和删除处理程序,那么您需要首先创建一个显式EventHandler值:

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.也就是说,如果您只是将 C# 代码转换为 F#,那么在这种情况下您可能不会获得太多收益。 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.您的逻辑非常必要,可变的isLoading字段和添加/删除事件处理程序之类的事情将使您的 F# 代码非常难看。 If you want to develop mobile applications with F#, then I would instead recommend looking at Fabulous , which lets you write nice functional code.如果您想使用 F# 开发移动应用程序,那么我建议您查看 Fabulous ,它可以让您编写漂亮的功能代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM