क्या .NET में अनुक्रमिक जेनेरिक कुंजी / मान युग्म वर्ग है?


79

मैं एक कुंजी / मूल्य जोड़ी वस्तु की तलाश कर रहा हूं जिसे मैं वेब सेवा में शामिल कर सकता हूं।

मैंने .NET की System.Collections.Generic.KeyValuePair<>कक्षा का उपयोग करने की कोशिश की , लेकिन यह वेब सेवा में ठीक से क्रमबद्ध नहीं है। एक वेब सेवा में, कुंजी और मान गुण क्रमबद्ध नहीं होते हैं, जो इस वर्ग को बेकार बनाते हैं, जब तक कि कोई इसे ठीक करने का तरीका नहीं जानता है।

क्या कोई अन्य सामान्य वर्ग है जो इस स्थिति के लिए इस्तेमाल किया जा सकता है?

मैं .NET की System.Web.UI.Pairकक्षा का उपयोग करूंगा , लेकिन यह अपने प्रकारों के लिए ऑब्जेक्ट का उपयोग करता है। एक सामान्य वर्ग का उपयोग करना अच्छा होगा, यदि केवल सुरक्षा के लिए।

जवाबों:


95

बस एक संरचना / वर्ग को परिभाषित करें।

[Serializable]
public struct KeyValuePair<K,V>
{
  public K Key {get;set;}
  public V Value {get;set;}
}

3
@ डंडी: यह जानकर कि कैसे वैलेंटाइट को हेज हो जाता है और समानता की तुलना करना जरूरी है
— लेप्पी

2
आईडीएकोड अब धारावाहिक है, 4.5 में (कम से कम JSON के साथ)
— 23'13 पर टॉम

@ जो: अपने निर्माता को लिखने के लिए स्वतंत्र महसूस करें।
— लीपी

@ लेप्पी मैंने किया, लेकिन इस महान जवाब पर सिर्फ एक अवलोकन।
— जो

यह कोशिश करने के बाद, मुझे यह बिल्ड त्रुटि मिल रही है। कृपया ठीक करने के लिए कोई विचार प्रदान करें। 'AttributeCollection' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where<KeyValuePair<string, object>>(IQueryable<KeyValuePair<string, object>>, Expression<Func<KeyValuePair<string, object>, bool>>)' requires a receiver of type 'IQueryable<KeyValuePair<string, object>>'
— कार्तिक

22

मुझे नहीं लगता कि Dictionary<>एक्सएमएल सीरियल करने योग्य नहीं है, जब मुझे एक वेब सेवा के माध्यम से एक डिक्शनरी ऑब्जेक्ट भेजने की आवश्यकता थी, तो मैंने Dictionary<>अपने आप को ऑब्जेक्ट को लपेटकर और समर्थन जोड़ने के लिए समाप्त कर दिया IXMLSerializable।

/// <summary>
/// Represents an XML serializable collection of keys and values.
/// </summary>
/// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
/// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
    #region Constants

    /// <summary>
    /// The default XML tag name for an item.
    /// </summary>
    private const string DEFAULT_ITEM_TAG = "Item";

    /// <summary>
    /// The default XML tag name for a key.
    /// </summary>
    private const string DEFAULT_KEY_TAG = "Key";

    /// <summary>
    /// The default XML tag name for a value.
    /// </summary>
    private const string DEFAULT_VALUE_TAG = "Value";

    #endregion

    #region Protected Properties

    /// <summary>
    /// Gets the XML tag name for an item.
    /// </summary>
    protected virtual string ItemTagName
    {
        get
        {
            return DEFAULT_ITEM_TAG;
        }
    }

    /// <summary>
    /// Gets the XML tag name for a key.
    /// </summary>
    protected virtual string KeyTagName
    {
        get
        {
            return DEFAULT_KEY_TAG;
        }
    }

    /// <summary>
    /// Gets the XML tag name for a value.
    /// </summary>
    protected virtual string ValueTagName
    {
        get
        {
            return DEFAULT_VALUE_TAG;
        }
    }

    #endregion

    #region Public Methods

    /// <summary>
    /// Gets the XML schema for the XML serialization.
    /// </summary>
    /// <returns>An XML schema for the serialized object.</returns>
    public XmlSchema GetSchema()
    {
        return null;
    }

    /// <summary>
    /// Deserializes the object from XML.
    /// </summary>
    /// <param name="reader">The XML representation of the object.</param>
    public void ReadXml(XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;

        reader.Read();

        if (wasEmpty)
        {
            return;
        }

        while (reader.NodeType != XmlNodeType.EndElement)
        {
            reader.ReadStartElement(ItemTagName);

            reader.ReadStartElement(KeyTagName);
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement(ValueTagName);
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }

        reader.ReadEndElement();
    }

    /// <summary>
    /// Serializes this instance to XML.
    /// </summary>
    /// <param name="writer">The writer to serialize to.</param>
    public void WriteXml(XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement(ItemTagName);

            writer.WriteStartElement(KeyTagName);
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement(ValueTagName);
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }

    #endregion
}

5
ओपी शब्दकोश का उल्लेख बिल्कुल नहीं करता है। सवाल एक कुंजी / मूल्य जोड़ी को क्रमबद्ध करने के बारे में है। आपका उत्तर संबंधित है, लेकिन मुझे लगता है कि यह मूल मुद्दे से हटता है।
— एडम राल्फ

17

आपको यह कारण मिल जाएगा कि KeyValuePairs को इस MSDN ब्लॉग पोस्ट पर क्रमबद्ध क्यों नहीं किया जा सकता है

संरचना जवाब सबसे आसान समाधान है, हालांकि एकमात्र समाधान नहीं है। एक "बेहतर" समाधान एक कस्टम KeyValurPair वर्ग लिखने के लिए है जो Serializable है।


9
ध्यान दें कि DataContractSerializer (यह .NET 3.0 और WCF के साथ आता है) KeyValuePair <,> को पूरी तरह से संभाल सकता है। तो यह एक सामान्य क्रमांकन मुद्दा नहीं है, बल्कि आपके द्वारा उपयोग किए जाने वाले विशिष्ट धारावाहिक का एक मुद्दा है (जैसा कि MSDN पेज का लिंक बताता है)।
— क्रिश्चियन.के।

आपका MSDN ब्लॉग पोस्ट ( blogs.msdn.microsoft.com/seshadripv/archive/2005/11/02/… ) अब एक मृत लिंक है
— brewmanz

7
 [Serializable]
 public class SerializableKeyValuePair<TKey, TValue>
    {

        public SerializableKeyValuePair()
        {
        }

        public SerializableKeyValuePair(TKey key, TValue value)
        {
            Key = key;
            Value = value;
        }

        public TKey Key { get; set; }
        public TValue Value { get; set; }

    }

1

4.0 फ्रेमवर्क में, वर्गों के टपल परिवार के अलावा भी है जो क्रमबद्ध और समान हैं। आप उपयोग कर सकते हैं Tuple.Create(a, b)या new Tuple<T1, T2>(a, b)।


16
हालांकि टुपल प्रकार सीरियल योग्य हैं, लेकिन वे दुर्भाग्य से XML सीरियल नहीं हैं
— चीता

0

KeyedCollection एक प्रकार का शब्दकोश है जिसे बिना किसी बकवास के सीधे xml में क्रमबद्ध किया जा सकता है। एकमात्र मुद्दा यह है कि आपको मानों को एक्सेस करना होगा: coll ["key"]। मान;


मुझे नहीं लगता कि KeyedCollection को किसी WebService के भीतर क्रमबद्ध किया जा सकता है क्योंकि इसमें कोई सार्वजनिक कंस्ट्रक्टर नहीं है। [Serializable] -attribute केवल रीमोट करने के लिए काम करता है।
— मार्टिन


0

DataContractSerializer का उपयोग करें क्योंकि यह कुंजी मान जोड़ी को संभाल सकता है।

    public static string GetXMLStringFromDataContract(object contractEntity)
    {
        using (System.IO.MemoryStream writer = new System.IO.MemoryStream())
        {
            var dataContractSerializer = new DataContractSerializer(contractEntity.GetType());
            dataContractSerializer.WriteObject(writer, contractEntity);
            writer.Position = 0;
            var streamReader = new System.IO.StreamReader(writer);
            return streamReader.ReadToEnd();
        }
    }

0

DataTableJSON के लिए सीरीज़ किए जाने के लिए (पूरी तरह से) रैपिंग डेटा के लिए मेरा पसंदीदा संग्रह है, क्योंकि अतिरिक्त की आवश्यकता के बिना इसका विस्तार करना आसान है structऔर इसके लिए धारावाहिक परिवर्तन की तरह काम करता हैTuple<>[]

शायद सबसे साफ तरीका नहीं है, लेकिन मैं इसे सीधे वर्गों में शामिल करना और उपयोग करना पसंद करता हूं (जिसे क्रमबद्ध किया जाएगा), बजाय एक नया घोषित करने के struct

class AnyClassToBeSerialized
{
    public DataTable KeyValuePairs { get; }

    public AnyClassToBeSerialized
    {
        KeyValuePairs = new DataTable();
        KeyValuePairs.Columns.Add("Key", typeof(string));
        KeyValuePairs.Columns.Add("Value", typeof(string));
    }

    public void AddEntry(string key, string value)
    {
        DataRow row = KeyValuePairs.NewRow();
        row["Key"] = key; // "Key" & "Value" used only for example
        row["Value"] = value;
        KeyValuePairs.Rows.Add(row);
    }
}

-3

आप उपयोग कर सकते हैं Tuple<string,object>

Tupleउपयोग के बारे में अधिक जानकारी के लिए इसे देखें : C # 4.0 में Tuple के साथ कार्य करना


16
यह पहले से ही सुझाया गया था । दुर्भाग्य से, टपल क्लास एक्सएमएल सीरियल नहीं है।
— दान हर्बर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.