च #

2010-06-07 12 views
11

मैं रिकर्सिवली सब एक वस्तुओं के गुण और उप-प्रकार गुण आदि मेरे ऑब्जेक्ट मॉडल का अनुसरण करता है के रूप में बाहर मुद्रित करने के लिए कोशिश कर रहा हूँ प्रकार के साथ मिलान पैटर्न ...च #

type suggestedFooWidget = { 
    value: float ; 
    hasIncreasedSinceLastPeriod: bool ; 
} 

type firmIdentifier = { 
    firmId: int ; 
    firmName: string ; 
} 
type authorIdentifier = { 
    authorId: int ; 
    authorName: string ; 
    firm: firmIdentifier ; 
} 

type denormalizedSuggestedFooWidgets = { 
    id: int ; 
    ticker: string ; 
    direction: string ; 
    author: authorIdentifier ; 
    totalAbsoluteWidget: suggestedFooWidget ; 
    totalSectorWidget: suggestedFooWidget ; 
    totalExchangeWidget: suggestedFooWidget ; 
    todaysAbsoluteWidget: suggestedFooWidget ; 
    msdAbsoluteWidget: suggestedFooWidget ; 
    msdSectorWidget: suggestedFooWidget ; 
    msdExchangeWidget: suggestedFooWidget ; 
} 

और मेरे प्रत्यावर्तन पर आधारित है पैटर्न मिलान निम्नलिखित ...

let rec printObj (o : obj) (sb : StringBuilder) (depth : int) 
    let props = o.GetType().GetProperties() 
    let enumer = props.GetEnumerator() 
    while enumer.MoveNext() do 
     let currObj = (enumer.Current : obj) 
     ignore <| 
      match currObj with 
      | :? string as s -> sb.Append(s.ToString()) 
      | :? bool as c -> sb.Append(c.ToString()) 
      | :? int as i -> sb.Append(i.ToString()) 
      | :? float as i -> sb.Append(i.ToString()) 
      | _ -> printObj currObj sb (depth + 1) 
    sb 

डिबगर मुझे लगता है कि currObj प्रकार स्ट्रिंग, पूर्णांक, नाव, आदि की है लेकिन यह हमेशा तल पर डिफ़ॉल्ट रूप मामले को कूदता में। कुछ पता है कि ऐसा क्यों हो रहा है?

उत्तर

4

यहाँ मैं कैसे है यह काम करने के लिए मिल गया ...

let getMethod = prop.GetGetMethod() 
let value = getMethod.Invoke(o, Array.empty) 
    ignore <| 
     match value with 
     | :? float as f -> sb.Append(f.ToString() + ", ") |> ignore 
          ... 
0

आप इस के बजाय की तरह कुछ करना चाहते हैं।

let rec printObj (o : obj) (sb : StringBuilder) (depth : int) 
    let props = o.GetType().GetProperties() :> IEnumerable<PropertyInfo> 
    let enumer = props.GetEnumerator() 
    while enumer.MoveNext() do 
     let currObj = (enumer.Current.GetValue (o, null)) :> obj 
     ignore <| 
      match currObj with 
      | :? string as s -> sb.Append(s.ToString()) 
      | :? bool as c -> sb.Append(c.ToString()) 
      | :? int as i -> sb.Append(i.ToString()) 
      | :? float as i -> sb.Append(i.ToString()) 
      | _ -> printObj currObj sb (depth + 1) 
    sb 

यह Array वर्ग पर MSDN डॉक्स से आ रही है:

.नेट फ्रेमवर्क संस्करण 2.0 में, सरणी वर्ग को लागू करता है System.Collections.Generic.IList, सिस्टम .Collections.Generic.ICollection, और System.Collections.Generic.IEnumerable जेनेरिक इंटरफेस। कार्यान्वयन रन टाइम पर सरणियों के लिए प्रदान की है, और इसलिए प्रलेखन निर्माण उपकरण को दिखाई नहीं कर रहे हैं। नतीजतन, सामान्य इंटरफेस सरणी वर्ग के लिए घोषणा वाक्य रचना में दिखाई नहीं देते, और कोई संदर्भ इंटरफ़ेस सदस्यों को बताया कि केवल सामान्य इंटरफ़ेस प्रकार को एक सरणी कास्टिंग द्वारा सुलभ हैं के लिए विषयों (स्पष्ट देखते हैं इंटरफ़ेस कार्यान्वयन)। कुंजी बात के बारे में पता करने के लिए जब आप इन इंटरफेस में से एक कि सदस्यों को जो जोड़ने, सम्मिलित करें, या हटाने तत्वों NotSupportedException फेंक है एक सरणी डाली हो।

+0

संकलक कह रहा है: क्षेत्र, निर्माता या सदस्य 'getValue' – PhilBrown

+0

@philbrowndotcom परिभाषित नहीं है - मैं तुम्हें एक डाली क्या करने की जरूरत है। – ChaosPandion

0

क्या आप सुनिश्चित हैं कि कार्यक्रम अपेक्षित व्यवहार नहीं कर रहा है? डीबगर स्पैन हमेशा विश्वसनीय नहीं होते हैं।

+0

समस्या यह है कि enumer.Current.GetValue वास्तव में मूल्य नहीं है, यह एक PropertyInfo ऑब्जेक्ट है। यहां कुछ अमूर्तता है जिसने मुझे भ्रमित कर दिया है। – PhilBrown

+0

तो आप GetType/GetProperties/आदि के साथ किस एपीआई का उपयोग कर रहे हैं? शायद इसके लिए दस्तावेज़ इसे समझाते हैं? – Brian

1

अपने उदाहरण में, enumer.Current एक PropertyInfo युक्त एक वस्तु है। इसका मतलब है कि currObj हमेशा एक PropertyInfo ऑब्जेक्ट है, और हमेशा आपके मैच स्टेटमेंट में अंतिम मामले के अनुरूप होगा।

जब से तुम संपत्ति का मूल्य के प्रकार में रुचि रखते हैं, तो आप PropertyInfo की विधि getValue() कॉल करने के लिए (ChaosPandion के जवाब के रूप में) संपत्ति के वास्तविक मूल्य को पाने के लिए की आवश्यकता होगी ।

के बाद से एक गणनाकार वस्तुओं के रूप में अपने मूल्यों को देता है, तो आप भी इससे पहले कि आप getValue उपयोग कर सकते हैं एक PropertyInfo को enum.current कास्ट करने के लिए की आवश्यकता होगी।

let currObj = unbox<PropertyInfo>(enumer.Current).GetValue (o, null) 
इस बदलाव के साथ

साथ की जगह

let currObj = (enumer.Current : obj) 

, मैं अपने कोड (FSI में) काम करने के लिए प्राप्त कर सकते हैं की कोशिश:

> let test = {authorId = 42; authorName = "Adams"; firm = {firmId = 1; firmName = "GloboCorp inc."} };; 
> string <| printObj test (new StringBuilder()) 1;; 
val it : string = "42Adams1GloboCorp inc." 
14

दूसरों के रूप में बताया गया है, आपको संपत्ति का मूल्य प्राप्त करने के लिए GetValue सदस्य को आमंत्रित करने की आवश्यकता है - पुनरावृत्ति जिसे आपने इसे लागू किया है PropertyInfo ऑब्जेक्ट्स पर, जो "संपत्ति के वर्णनकर्ता" हैं - वास्तविक मूल्य नहीं। हालांकि, मुझे समझ में नहीं आता कि GetEnumerator और while लूप स्पष्ट रूप से क्यों उपयोग कर रहे हैं जब एक ही चीज़ for लूप का उपयोग करके लिखी जा सकती है।

इसके अलावा, आप sb.Append कॉल द्वारा दिए गए मान को अनदेखा करने की जरूरत नहीं है - तो आप बस समग्र परिणाम के रूप में यह लौट सकते हैं (क्योंकि यह StringBuilder है)। यह वास्तव में कोड को अधिक कुशल बना देगा (क्योंकि यह पूंछ-कॉल अनुकूलन सक्षम बनाता है)। आखिरी बिंदु के रूप में, आपको sb.Append(..) में ToString की आवश्यकता नहीं है, क्योंकि Append विधि अधिभारित है और सभी मानक प्रकारों के लिए काम करता है।

तो कुछ सरलीकरण के बाद, आप कुछ इस तरह प्राप्त कर सकते हैं (यह वास्तव में depth पैरामीटर का उपयोग नहीं कर रहा है, लेकिन मुझे लगता है कि आप बाद में कुछ करने के लिए इसका उपयोग करना चाहते):

let rec printObj (o : obj) (sb : StringBuilder) (depth : int) = 
    let props = o.GetType().GetProperties() 
    for propInfo in props do 
    let propValue = propInfo.GetValue(o, null) 
    match propValue with 
    | :? string as s -> sb.Append(s) 
    | :? bool as c -> sb.Append(c) 
    | :? int as i -> sb.Append(i) 
    | :? float as i -> sb.Append(i) 
    | _ -> printObj currObj sb (depth + 1) 
+0

मैं डाल रहा हूं |> अनदेखा और लौट रहा है() – PhilBrown

संबंधित मुद्दे