2010-08-14 6 views
65

मैं निम्नलिखित गुमनाम प्रकार है:सी # में अनाम प्रकार को कुंजी/मूल्य सरणी में परिवर्तित करें?

new {data1 = "test1", data2 = "sam", data3 = "bob"} 

मैं एक विधि है कि इस में ले जाएगा, और किसी सरणी या शब्दकोश में उत्पादन कुंजी मान जोड़े की जरूरत है।

"data1=test1&data2=sam&data3=bob" 

उत्तर

96

यह पूरा करने के लिए प्रतिबिंब का सिर्फ एक छोटा सा लेता है:

मेरा लक्ष्य तो मैं अंत में निम्न स्ट्रिंग में में जोड़ होगा एक HttpRequest में पोस्ट डेटा के रूप में उपयोग किया जा सके।

var a = new { data1 = "test1", data2 = "sam", data3 = "bob" }; 
var type = a.GetType(); 
var props = type.GetProperties(); 
var pairs = props.Select(x => x.Name + "=" + x.GetValue(a, null)).ToArray(); 
var result = string.Join("&", pairs); 
+5

var dict = props.ToDictionary (x => x.Name, x => x.GetValue (a_source, null)) – Jordan

+18

हमें यह मिला है ... हम इसे एक लाइनर बना सकते हैं: 'var dict = a .GetType()। GetProperties()। ToDictionary (x => x.Name, x => x.GetValue (ए, शून्य)); ' – kape123

+0

@ kape123, वास्तव में।वास्तव में, नवीनतम .NET संस्करणों को अब 'ToArray()' पर कॉल की आवश्यकता नहीं है, जो कि अच्छा है। किसी भी दर पर, प्रतिक्रिया के रूप में प्रतिक्रिया शब्द के बिना SO में अच्छी तरह फिट बैठती है, इसलिए मैं इसे छोड़ दूंगा। – kbrimington

54

आप .NET 3.5 SP1 या .NET 4 का उपयोग कर रहे हैं, तो आप कर सकते हैं (ab) इस के लिए RouteValueDictionary का उपयोग करें। यह IDictionary<string, object> लागू करता है और इसमें एक निर्माता है जो object स्वीकार करता है और गुणों को कुंजी-मूल्य जोड़ों में परिवर्तित करता है।

यह आपकी क्वेरी स्ट्रिंग बनाने के लिए कुंजी और मानों के माध्यम से लूप के लिए छोटा होगा।

private void AddValues(object values) 
    { 
     if (values != null) 
     { 
      foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values)) 
      { 
       object obj2 = descriptor.GetValue(values); 
       this.Add(descriptor.Name, obj2); 
      } 
     } 
    } 

पूर्ण स्रोत यहाँ है:

+4

मैं "दुर्व्यवहार" कहता हूं क्योंकि कक्षा मूल रूप से रूटिंग के लिए डिज़ाइन की गई थी (या कम से कम इसका नाम और नामस्थान इसका अर्थ है)। हालांकि, इसमें कोई रूटिंग-विशिष्ट कार्यक्षमता नहीं है और पहले से ही अन्य सुविधाओं के लिए उपयोग की जा रही है (जैसे एएसपी.नेट एमवीसी 'एचटीएमएलहेल्पर' एक्सटेंशन विधियों में एचटीएमएल विशेषताओं के लिए अज्ञात वस्तुओं को शब्दकोश में परिवर्तित करना। – GWB

+0

मैंने बिल्कुल यह किया है लेकिन अब मुझे जाना होगा रूटवेल्यू डिक्शनरी से वापस किसी भी वस्तु पर, कोई विचार ?? – Joshy

+0

यह इसका दुरुपयोग भी नहीं है .. माइक्रोसॉफ्ट यह करता है। उदाहरण के लिए, जब आप HtmlHelper को कॉल करते हैं। टेक्स्टबॉक्स ... आपको एक अनाम प्रकार गुजरना है विशेषता मान सेट करने के लिए। यह वास्तव में रेजर में बाध्यकारी त्रुटि का कारण बनता है (उदाहरण के लिए @ Html.Partial ("~/Shared/_PartialControl.cshtml", नया {id = "id", value = "value"} को कॉल करने का प्रयास करें), और यह आंशिक दृश्य में घोषित @ मॉडल गतिशील के साथ भी बाध्यकारी त्रुटि फेंक देगा। टेक्स्टबॉक्स विधि आंतरिक रूप से "सार्वजनिक स्थैतिक रूट ValueDictionary AnonymousObjectToHtmlAttributes (ऑब्जेक्ट htmlAttributes)" कहती है, जो रूटवेल्यू डिक्शनरी लौट रही है। तो आप वहां जाते हैं। – Triynko

24

यहाँ कैसे वे RouteValueDictionary में ऐसा है http://pastebin.com/c1gQpBMG

+0

मैंने पेस्टबिन से कोड का उपयोग करने की कोशिश की और विजुअल स्टूडियो कह रहा था कि शब्दकोश विधियों का एक समूह लागू नहीं किया गया था। मुझे IDictionary को एक स्पष्ट कलाकार करना था। मैंने बस कुछ "this._dictionary" को "((IDictionary ) में बदल दिया है।" –

1

@ kbrimington के समाधान के लिए एक अच्छा विस्तार विधि बनाता है - मेरी मेरे मामले एक HtmlString

public static System.Web.HtmlString ToHTMLAttributeString(this Object attributes) 
    { 
     var props = attributes.GetType().GetProperties(); 
     var pairs = props.Select(x => string.Format(@"{0}=""{1}""",x.Name,x.GetValue(attributes, null))).ToArray(); 
     return new HtmlString(string.Join(" ", pairs)); 
    } 
लौटने

मैं इसका उपयोग रेजर एमवीसी व्यू में मनमाने ढंग से विशेषताओं को छोड़ने के लिए कर रहा हूं। मैंने RoutealueDictionary का उपयोग करके कोड के साथ शुरुआत की और परिणामों पर लूपिंग शुरू की लेकिन यह बहुत साफ है।

+5

यह पहले से ही बॉक्स में मौजूद है (कम से कम, यह अब करता है): 'HtmlHelper.AnonymousObjectToHtmlAttributes' – Andrew

1

मैं कुछ इस तरह किया:

public class ObjectDictionary : Dictionary<string, object> 
{ 
    /// <summary> 
    /// Construct. 
    /// </summary> 
    /// <param name="a_source">Source object.</param> 
    public ObjectDictionary(object a_source) 
     : base(ParseObject(a_source)) 
    { 

    } 

    /// <summary> 
    /// Create a dictionary from the given object (<paramref name="a_source"/>). 
    /// </summary> 
    /// <param name="a_source">Source object.</param> 
    /// <returns>Created dictionary.</returns> 
    /// <exception cref="ArgumentNullException">Thrown if <paramref name="a_source"/> is null.</exception> 
    private static IDictionary<String, Object> ParseObject(object a_source) 
    { 
     #region Argument Validation 

     if (a_source == null) 
      throw new ArgumentNullException("a_source"); 

     #endregion 

     var type = a_source.GetType(); 
     var props = type.GetProperties(); 

     return props.ToDictionary(x => x.Name, x => x.GetValue(a_source, null)); 
    } 
} 
1

@ एक RouteValueDictionary का उपयोग करने का GWB के सुझाव पर बिल्डिंग, मैं इस पुनरावर्ती क्रिया नेस्टेड गुमनाम प्रकार का समर्थन करने के लिए लिखा था, अपने माता पिता के चाबियाँ द्वारा उन नेस्टेड मापदंडों लगाकर।

public static string EncodeHtmlRequestBody(object data, string parent = null) { 
    var keyValuePairs = new List<string>(); 
    var dict = new RouteValueDictionary(data); 

    foreach (var pair in dict) { 
     string key = parent == null ? pair.Key : parent + "." + pair.Key; 
     var type = pair.Value.GetType(); 
     if (type.IsPrimitive || type == typeof(decimal) || type == typeof(string)) { 
      keyValuePairs.Add(key + "=" + Uri.EscapeDataString((string)pair.Value).Replace("%20", "+")); 
     } else { 
      keyValuePairs.Add(EncodeHtmlRequestBody(pair.Value, key)); 
     } 
    } 

    return String.Join("&", keyValuePairs); 
} 

उदाहरण उपयोग:

var data = new { 
    apiOperation = "AUTHORIZE", 
    order = new { 
     id = "order123", 
     amount = "101.00", 
     currency = "AUD" 
    }, 
    transaction = new { 
     id = "transaction123" 
    }, 
    sourceOfFunds = new { 
     type = "CARD", 
     provided = new { 
      card = new { 
       expiry = new { 
        month = "1", 
        year = "20" 
       }, 
       nameOnCard = "John Smith", 
       number = "4444333322221111", 
       securityCode = "123" 
      } 
     } 
    } 
}; 

string encodedData = EncodeHtmlRequestBody(data); 

encodedData हो जाता है:

"apiOperation=AUTHORIZE&order.id=order123&order.amount=101.00&order.currency=AUD&transaction.id=transaction123&sourceOfFunds.type=CARD&sourceOfFunds.provided.card.expiry.month=1&sourceOfFunds.provided.card.expiry.year=20&sourceOfFunds.provided.card.nameOnCard=John+Smith&sourceOfFunds.provided.card.number=4444333322221111&sourceOfFunds.provided.card.securityCode=123"

आशा है कि यह एक ऐसी ही स्थिति में किसी और में मदद करता है।

संपादित करें: जैसा कि ड्र्यूजी ने बताया, यह सरणी का समर्थन नहीं करता है। अज्ञात प्रकार के साथ मनमाने ढंग से घोंसले वाले सरणी के लिए समर्थन को सही ढंग से कार्यान्वित करने के लिए गैर-तुच्छ होगा, और जैसा कि मैंने उपयोग किए गए एपीआई में से कोई भी एरे स्वीकार नहीं किया है (मुझे यकीन नहीं है कि फॉर्म एन्कोडिंग के साथ उन्हें क्रमबद्ध करने का मानकीकृत तरीका भी है) अगर आपको उनका समर्थन करने की ज़रूरत है तो मैं आपको लोगों को छोड़ दूंगा।

+0

हेड्स, यह सरणी को सही ढंग से संभाल नहीं करता है। ओवरफ्लो ढेर होगा। को इस की तरह कुछ चाहिए यदि (type.IsArray) { var arr = pair. string के रूप में वैल्यू []; अगर (arr! = Null) { foreach (arr में var s) { keyValuePairs.Add ((key + "[] =" + s)। जगह ("", "+")); } } } – DrewG