2016-01-03 5 views
5

Ho una web API C# che uso per accedere a una libreria F #. Ho creato una DU dei tipi che desidero restituire e utilizzare la corrispondenza dei modelli per scegliere quale tornare al controller C#.Lavorare con i tipi F # in C#

Nel controller C# come accedere ai dati del tipo restituito dalla chiamata di funzione alla libreria F #?

C# controller

public HttpResponseMessage Post() 
{ 
    var _result = Authentication.GetAuthBehaviour(); 
    //Access item1 of my tuple 
    var _HTTPStatusCode = (HttpStatusCode)_result.item1; 
    //Access item2 of my tuple 
    var _body = (HttpStatusCode)_result.item2; 
    return base.Request.CreateResponse(_HTTPStatusCode, _body); 
} 

F # Tipi

module Types = 
    [<JsonObject(MemberSerialization=MemberSerialization.OptOut)>] 
    [<CLIMutable>] 
    type ValidResponse = { 
     odata: string; 
     token: string; 
    } 

    [<JsonObject(MemberSerialization=MemberSerialization.OptOut)>] 
    [<CLIMutable>] 
    type ErrorResponse = { 
     code: string; 
     message: string; 
     url: string; 
    } 

    type AuthenticationResponse = 
    | Valid of int * ValidResponse 
    | Error of int * ErrorResponse 

F funzione #

module Authentication = 
    open Newtonsoft.Json 

    let GetAuthBehaviour() = 
     let behaviour = GetBehaviour.Value.authentication 
     match behaviour.statusCode with 
     | 200 -> 
      let deserializedAuthenticationResponse = JsonConvert.DeserializeObject<Types.ValidResponse>(behaviour.body) 
      Types.Valid (behaviour.statusCode, deserializedAuthenticationResponse) 
     | _ -> 
      let deserializedAuthenticationResponse = JsonConvert.DeserializeObject<Types.ErrorResponse>(behaviour.body) 
      Types.Error (behaviour.statusCode, deserializedAuthenticationResponse) 
+2

C'è un esempio di come affrontare i sindacati discriminati in C# qui http://stackoverflow.com/questions/23843142/f-discriminated-union-usage-from-c-sharp. Suggerisce anche che, in base alle linee guida sulla progettazione di F #, dovresti forse considerare di nascondere il sindacato discriminato dall'API disponibile in C#. Le tuple F # verranno automaticamente convertite in istanze del tipo 'Tuple <>' appropriato, in modo da poter facilmente restituire una tupla da 3 t dal codice F # e avere molto meno mal di testa. – jpe

risposta

5

F # Discriminazione I sindacati sono compilati come classi astratte, con ogni caso essere una classe annidata derivata. Da C#, è possibile accedere ai casi tentando di downcast il risultato da GetAuthBehaviour:

public HttpResponseMessage Post() 
{ 
    var result = Authentication.GetAuthBehaviour(); 

    var valid = result as Types.AuthenticationResponse.Valid; 
    if (valid != null) 
    { 
     int statusCode = valid.Item1; 
     Types.ValidResponse body = valid.Item2; 
     return this.CreateResponse(statusCode, body); 
    } 

    var error = result as Types.AuthenticationResponse.Error; 
    if (error != null) 
    { 
     int statusCode = error.Item1; 
     Types.ErrorResponse body = error.Item2; 
     return this.CreateResponse(statusCode, body); 
    } 

    throw new InvalidOperationException("..."); 
} 

Si noti che il compilatore C# non sa che hai gestito tutti i casi, quindi avrete bisogno di fornire un filiale che gestisce il caso in cui result non è né ValidError. Qui, ho semplicemente lanciato un'eccezione come esempio, ma in un'API Web, sarebbe probabilmente più appropriato restituire un codice di stato 500.

Tutto ciò che ha detto, però, perché avere anche il problema di scrivere e gestire i controller in C#? È possibile write an ASP.NET Web API purely in F#.