it-swarm-vi.tech

Có một lớp cặp Khóa/Giá trị chung nối tiếp trong .NET không?

Tôi đang tìm kiếm một đối tượng cặp khóa/giá trị mà tôi có thể đưa vào một dịch vụ web.

Tôi đã thử sử dụng .NET's System.Collections.Generic.KeyValuePair<> class, nhưng nó không được tuần tự hóa đúng cách trong một dịch vụ web. Trong một dịch vụ web, các thuộc tính Khóa và Giá trị không được tuần tự hóa, làm cho lớp này trở nên vô dụng, trừ khi có ai đó biết cách khắc phục điều này.

Có lớp chung nào khác có thể được sử dụng cho tình huống này không?

Tôi sẽ sử dụng .NET's System.Web.UI.Pair class, nhưng nó sử dụng Object cho các loại của nó. Sẽ thật tuyệt khi sử dụng lớp Chung, nếu chỉ vì loại an toàn.

74
Dan Herbert

Chỉ cần định nghĩa một cấu trúc/lớp.

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

Tôi không nghĩ rằng có Dictionary<> tự nó không phải là tuần tự hóa XML, khi tôi cần gửi một đối tượng từ điển thông qua một dịch vụ web, tôi đã tự mình kết thúc đối tượng Dictionary<> và thêm hỗ trợ cho 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
}
22
Compile This

Bạn sẽ tìm thấy lý do tại sao KeyValuePairs không thể được đăng tuần tự tại Bài đăng trên Blog MSDN

Câu trả lời Struct là giải pháp đơn giản nhất, tuy nhiên không phải là giải pháp duy nhất. Một giải pháp "tốt hơn" là viết một lớp KeyValurPair tùy chỉnh có khả năng nối tiếp.

17
user56931
 [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; }

    }
5
GregoryBrad

Trong Khung công tác 4.0, cũng có sự bổ sung của nhóm các lớp Tuple có khả năng tuần tự hóa và công bằng. Bạn có thể sử dụng Tuple.Create(a, b) hoặc new Tuple<T1, T2>(a, b).

1
Peter Oehlert

Sử dụng DataContractSerializer vì nó có thể xử lý Cặp giá trị khóa.

    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
Hasse

KeyedCollection là một loại từ điển có thể được nối tiếp trực tiếp thành xml mà không có bất kỳ sự vô nghĩa nào. Vấn đề duy nhất là bạn phải truy cập các giá trị bằng cách: coll ["key"]. Value;

0
Will

DataTable là bộ sưu tập yêu thích của tôi để (chỉ) gói dữ liệu được tuần tự hóa thành JSON, vì nó dễ dàng mở rộng mà không cần thêm struct & hoạt động như một sự thay thế tuần tự hóa cho Tuple<>[]

Có thể không phải là cách sạch nhất, nhưng tôi thích bao gồm và sử dụng nó trực tiếp trong các lớp (sẽ được tuần tự hóa), thay vì khai báo một struct mới

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);
    }
}
0
Teodor Tite

XmlSerializer không hoạt động với Từ điển. Ồ, và nó cũng có vấn đề với KeyValuePairs

http://www.codeproject.com/Tips/314447/XmlSerializer-doesnt-work-with-Dictaries-Oh-and

0
Akodo_Shado