C'è stata una domanda simile recentemente dove member constraints were used in the type declaration.
Non sono sicuro di come correggere il campione per farlo compilare, ma non sarei sorpreso se ciò non fosse possibile. I vincoli dei membri sono progettati per essere utilizzati con parametri di tipo risolti staticamente e specialmente con le funzioni o membri inline
e non penso che sia un codice F # idiomatico per usarli con i parametri di tipo di una classe.
penso che una soluzione più idiomatica al tuo esempio potrebbe essere quello di definire un'interfaccia:
type INamed =
abstract Name : string
type ListEntryViewModel<'T when 'T :> INamed>(model:'T) =
member this.Name = model.Name
(In realtà, il ListEntryViewModel
probabilmente non ha bisogno di un parametro di tipo e possono solo prendere INamed
come parametro del costruttore , ma ci può essere qualche beneficio per iscritto in questo modo.)
Ora, è comunque possibile utilizzare la tipizzazione anatra e utilizzare ListEntryViewModel
sulle cose che hanno Name
proprietà, ma non implementano l'interfaccia INamed
! Questo può essere fatto scrivendo una funzione inline
che restituisce INamed
e usa i vincoli membro statiche per catturare l'Name
proprietà esistente:
let inline namedModel< ^T when ^T : (member Name : string)> (model:^T)=
{ new INamed with
member x.Name =
(^T : (member Name : string) model) }
È quindi possibile creare la tua vista del modello scrivendo ListEntryViewModel(namedModel someObj)
dove someObj
non deve implementare l'interfaccia , ma necessita solo della proprietà Name
.
Preferirei questo stile, perché prendendo un'interfaccia, è possibile documentare meglio ciò che si richiede dal modello. Se hai altri oggetti che non si adattano allo schema, puoi adattarli, ma se stai scrivendo un modello, implementare un'interfaccia è un buon modo per assicurarsi che esponga tutte le funzionalità richieste.
fonte
2012-10-22 13:02:27
Si noti che questo non è realmente "digitazione anatra", ma piuttosto una digitazione strutturale (secondaria). – Eyvind