2017-12-28 12 views
1

それぞれが同じWCFサービスの異なるバージョンを指し示す3つのWsdlServiceタイププロバイダーを持ち、基礎となるMyService.ServiceTypes.Ticketはほとんど同じです。私はWsdlServiceプロバイダを使用しているので、ソースから取得したコードはサービスから使用するオブジェクトだけです。このプロジェクトは、古いプロジェクトのスライスを置き換え始めました。SvcUtil.exeによって生成されたすべてが未使用(yuck)であっても、ソースにチェックインされています。F#WsdlServiceプロバイダー:複数のプロバイダーで繰り返しマッピングコードを減らす

凝縮したい機能が非常に似ているので、code quotationsまたはhigher kinded typesが機能するかもしれません。私のユースケースは、私がF#の見積もりを使って見た例に似ていないし、HKTをまだ理解していない。

サービスバージョンが3つのみの場合、モジュールのVersionMappersのコピー貼り付けの方法はそれほど悪くありません。ただし、このサービスには約10種類のバージョンがあります。コピー貼り付けをもう一度やり直すことはできますが、これは関数型言語で処理できるもののような感じです。

マイ包括的な質問:私は、モジュールCanThisPseudoCodeBeRealに持っている、または私はコピー&ペーストの土地で自分を追い詰めているようなものに、モジュールVersionMappersに反復ticketxxToDomainコードを減らすためにいくつかのF#の方法はありますか?コード引用やHKTは実行可能な選択肢ですか?

`` `F#

module DataAccess = 
    type Service40 = WsdlService<My40ServiceUrl> 
    type Service41 = WsdlService<My41ServiceUrl> 
    type Service42 = WsdlService<My42ServiceUrl> 

// All the ticketXXToDomain functions look like they can be less copy-paste, but how? 
// Still, I think this F# approach is MUCH better than the monolith project we have where WCF SvcUtil.exe 
// generate everything for every version and we check that in to source. 
module VersionMappers = 
    open DataAccess 
    module Ticket = 
    let ticket40ToDomain (t : Service40.ServiceTypes.Ticket) = 
     MyCSharpProject.Pocos.Ticket(
     TicketId = t.TicketId 
     // with 10+ other fields 
     TicketType = t.TicketType) 
    let ticket41ToDomain (t : Service41.ServiceTypes.Ticket) = 
     MyCSharpProject.Pocos.Ticket(
     TicketId = t.TicketId 
     // with 10+ other fields 
     TicketType = t.TicketType) 
    let ticket42ToDomain (t : Service42.ServiceTypes.Ticket) = 
     MyCSharpProject.Pocos.Ticket(
     TicketId = t.TicketId 
     // with 10+ other fields 
     TicketType = t.TicketType) 

module CanThisPseudoCodeBeReal = 
    type ServiceTicket = 
    | V40Ticket of Service40.ServiceTypes.Ticket 
    | V41Ticket of Service41.ServiceTypes.Ticket 
    | V42Ticket of Service42.ServiceTypes.Ticket 
    let ticketToDomain (t : 'a when 'a is one case of ServiceTicket) = 
    // Now the compiler will hopefully complain if t.SomeField is not on 
    // all cases, and I am happy to handle that. 
    MyCSharpProject.Pocos.Ticket(
     // I am using fake field names for clarity. 
     // every VxxTicket has this field, no warning 
     TicketId = t.TicketId, 
     // compiler warns that only V40Ticket has this field 
     SomeV40Field = t.SomeV40Field, 
     // compiler warns that V42Ticket does not have this field 
     SomeV40And41Field = t.SomeV40And41Field 

    ) 

` ``

サイドノート:サービスなどServiceTypes.Ticketオブジェクトの周囲のすべてが、それらを取得するために呼び出すには、サービスのすべてのバージョン間で同じであるので、最新バージョンを指すWsdlServiceを1つだけ使用できます。これをソースコードから確認しました。他にもサービスの部分がありますので、人々がそれに不平を言う前に繰り返しを減らす方法があるかどうかを確認しようとしています。このプロジェクトは、F#とWsdlServiceプロバイダが既存のWCFサービスファサードの一部を「絞め殺す」ように試みるパイロットです。

答えて

3

F#は 'コンパイル時にジェネリック'(タイプセーフダックタイピング)を可能にするStatically Resolved Type Parameters知っ:toTCommonの署名がある

open System 

type T1 = { f1: string; f2: int; f3: DateTime } 
type T2 = { f2: int; f3: DateTime; f4: double } 

type TCommon = { f2: int; f3: DateTime } 

let inline toTCommon n = { 
    f2 = (^N : (member f2 : int) n) 
    f3 = (^N : (member f3 : DateTime) n) } 

val inline toTCommon : 
    n: ^N -> TCommon 
    when ^N : (member get_f2 : ^N -> int) and 
      ^N : (member get_f3 : ^N -> DateTime) 

f2 : intf3 : DateTime満足を有する任意のタイプこの。

関連する問題