2016-06-24 9 views
9

İlgili kayıtları tanımlamanın bir yolunu istiyorum. Örneğin,Kayıt varyasyonları F #

type Thing  = { field1: string; field2: float } 
type ThingRecord = { field1: string; field2: float; id: int; created: DateTime } 

veya çok klişe yazmaya gerek kalmadan, birinden diğerine dönüştürmek için bir yol ile birlikte

type UserProfile = { username: string; name: string; address: string } 
type NewUserReq = { username: string; name: string; address: string; password: string } 
type UserRecord = { username: string; name: string; address: string; encryptedPwd: string; salt: string } 

. Tam Hatta ilk örnek olacaktır:

type Thing = 
    { field1: string 
    field2: float } 
    with 
    member this.toThingRecord(id, created) = 
     { field1 = this.field1 
     field2 = this.field2 
     id = id 
     created = created } : ThingRecord 
and ThingRecord = 
    { field1: string 
    field2: float 
    id: int 
    created: DateTime } 
    with 
    member this.toThing() = 
     { field1 = this.field1 
     field2 = this.field2 } : Thing 

Eğer field10 vb kalkmak gibi, bir yükümlülük olarak alır.

Şu anda yansımayı kullanarak güvensiz (ve yavaş) bir şekilde yapıyorum.

with sözdizimi için, söz konusu gereksinimi karşılayacak şekilde kullanıcı tanımlarını kaydetmek için genişletilecek bir istek ekledim.

Ama bunu yapmak için belki de güvenli bir yol var mı? Belki tip sağlayıcıları ile?

cevap

4

Evet, bu F # 'ın aksi parlak zırhının içinde bir çatlak var. Bir kaydı kolayca almak veya genişletmek için orada evrensel bir çözüm olduğunu hissetmiyorum. Hiç şüphesiz bir iştah var - bu hatlar boyunca iyileştirmeleri savunan bir düzine us- saoir teslimini saydım - işte bir kaç öncü, oy kullanmaktan çekinmeyin: 1, 2, 3, 4, 5.

Elbette, sorunu çözmek için yapabileceğiniz şeyler vardır ve senaryounuza bağlı olarak sizin için harika olabilirler. Ama sonuçta - onlar geçici çözümler ve sen kurban gereken bir şey var:

  • Hız ve tip emniyet yansıma kullanarak,
  • Brevity Tür güvenli şekilde gitmek ve dönüşüm fonksiyonları arasında tam teşekküllü kayıtları var Onları, düz .NET sınıfları ve devralmaya geri dönmeye karar verdiğinizde, kayıtların sözdizimsel ve anlamsal iyiliği sağladığını tüm .

Tür sağlayıcılar, meta programlamaya yönelik gerçekten iyi bir araç olmadıklarından, bunu kesmezler. Bu onlar için tasarlandıkları şey değil. Onları bu şekilde kullanmaya çalışırsanız, bazı sınırlamalara uğrayacaksınız.

Bir için, yalnızca dış bilgilere dayanan türler sağlayabilirsiniz. Bu, bir tür sağlayıcıya sahip olabileceğiniz anlamına gelir.NET derleme yansıması ve buna dayalı bazı türetilmiş türler sunarak, oluşturduğunuz düzeneğin içine "göz atabilmeniz" mümkün değildir. Yani aynı mecliste daha önce tanımlanmış bir türden türetmenin yolu yoktur.

Projelerinizi tür sağlayıcısı çevresinde yapılandırarak bu konuda çalışabilirsiniz, ancak bu durum kulağa hoş geliyor. Ve o zaman bile, zaten yet kayıt türlerini sağlayamazsınız, bu yüzden yapabileceğiniz en iyi şey düz .NET sınıflarıdır. Bir veritabanı için ORM haritalama çeşit sağlama daha spesifik bir kullanım durumunda İçin

- Ben sadece hoş bir tip sağlayıcıları kullanabilir düşünün. Sadece genel bir metaprogramlama tesisi olarak değil.

+0

Bummer, Gelecek hafta, hiç kimsenin mevcut bir çözümü olmasaydı yapmayı planlıyordum, ama tip sağlayıcıların kayıt türlerini desteklemediği (şaşırtıcı) gerçek, bu fikri bir şekilde öldürüyor. –

+0

Eh, iki haftanız varsa, her zaman tip sağlayıcısı kayıt türlerini yayınlayarak başlayabilirsiniz;) – scrwtp

+0

Tamamen istekli, ama bana birkaç gün kazandı: nereden başlarım? –

1

Neden aşağıdaki gibi daha iç içe geçmiyorsunuz?

type Thing  = { Field1: string; Field2: float } 
type ThingRecord = { Thing : Thing; Id: int; Created: DateTime } 

veya

type UserProfile = { Username: string; Name: string; Address: string } 
type NewUserReq = { UserProfile: UserProfile; Password: string } 
type UserRecord = { UserProfile: UserProfile; EncryptedPwd: string; Salt: string } 

Dönüşüm fonksiyonları önemsiz şunlardır:

let toThingRecord id created thing = { Thing = thing; Id = id; Created = created } 
let toThing thingRecord = thingRecord.Thing 

Kullanımı:

> let tr = { Field1 = "Foo"; Field2 = 42. } |> toThingRecord 1337 (DateTime (2016, 6, 24));; 

val tr : ThingRecord = {Thing = {Field1 = "Foo"; 
           Field2 = 42.0;}; 
         Id = 1337; 
         Created = 24.06.2016 00:00:00;} 
> tr |> toThing;; 
val it : Thing = {Field1 = "Foo"; 
        Field2 = 42.0;} 
+0

İdeal olarak, evet, ama veritabanı o sevmez ve (hatta ideal olarak) bazen gerçekten düz bir şeyi temsil ediyoruz yuvalanmış bir yapıya sahip olmak garip. –

+0

Ve bazen yuvalamayı başlatıcı olmayan bir kesişen şeyler var. Örneğin. iç içe geçme, 'WithId > ',' >'; ama ben bir şey istiyorum. (id) .Timestamp (ts) '' thing.withTimestamp (ts) .withId (id) 'ile eşdeğerdir. –