2013-06-07 10 views
5

w JavaScripcie, można uzyskać dostęp do wszelkich właściwości obiektu z prostym pętli następującoprzelotowego F Rekord # jak JavaScript Object

var myObj = {x:1, y:2}; 
var i, sum=0; 
for(i in myObj) sum = sum + myObj[i]; 

Zastanawiam się, czy mogę zrobić coś podobnego z F #.

type MyObj = {x:int; y:int} 
let myObj = {x=1; y=2} 
let allValues:seq<int> = allPropertyValuesIn myObj //How do I implement allPropertyValuesIn 
let sum = allValues |> Seq.fold (+) 0 

Dziękuję za wejście

Edycja, aby wyjaśnić, dlaczego chcę zrobić czegoś takiego
pracuję nad generatorem pliku XML. Dane wejściowe są wierszami odczytanymi z bazy danych, a xsd jest predefiniowany.

Powiedzmy, że mam element "Produkt", który musi zostać wygenerowany iw zależności od reguły biznesowej, w produkcie może być 200 elementów podrzędnych, niektóre są wymagane, inne są opcjonalne. W następstwie doradztwa z this excellent blog miałem moje pierwsze (bardzo szorstki) projekt dla rekordu produktu:

1. type Product{ Price:Money; Name:Name; FactoryLocation:Address option ... } 
2. let product = {Price = Money(1.5); Name = Name ("Joe Tooth Paste"); ... } 
3. let child1 = createEl ("Price", product.Price) 
    .. 
203. let allChildren = child1 
         ::child2 
         ::child3 
         .. 
         ::[] 
404. let prodctEl = createElWithCildren ("Product", allChildren) 

Jest to bardzo uciążliwe i un-zwięzłe. Musi istnieć lepszy sposób na zrobienie tego w F #. Nie jestem też zbytnim krewnym w idei refleksji.

Czy są inne podejścia lub po prostu robię to źle?

+2

Jest to możliwe dzięki refleksji, ale nie sądzę, że istnieje szybka, bezpieczna alternatywa. –

+0

"Edytuj, aby wyjaśnić, dlaczego ..." Twój problem bardzo się zmienił:/jeśli chcesz zautomatyzować strukturę dziecka, musisz ZNORMALIZOWAĆ strukturę swojego dziecka (twoja struktura dziecka). – josejuan

Odpowiedz

5

Spróbuj tego:

open Microsoft.FSharp.Reflection 

type MyObj = {x:int; y:int} 
let myObj = {x=1; y=2} 
let allValues = FSharpType.GetRecordFields (myObj.GetType()) 
let sum = 
    allValues 
    |> Seq.fold 
     (fun s t -> s + int(t.GetValue(myObj).ToString())) 
     0 
printfn "%d" sum 

Jednakże, jak napomina John Palmer, nie ma zbyt wiele dobrych powodów do robienia czegoś takiego.

+2

Jest to jeden z tych dobrych powodów. Traktowanie struktury/rekordu jak mapy (struktura danych, która tak naprawdę jest strukturą) jest użyteczne, aby uzyskać jak najwięcej ze sprawdzania typów w publicznych interfejsach. Możesz użyć rekordu do przedstawienia wszystkich możliwych parametrów do interfejsu API (włączając w to Typy opcji, gdy jest to odpowiednie). Następnie za kulisami zrób coś takiego zamiast pisania ściany nazw członków, aby zbudować ładunek http. Podejście typu "ściana-imiona" jest szczególnie szkodliwe dla łatwości konserwacji. – Cogwheel

Powiązane problemy