मैं समझता हूं कि प्रोटोबफ.नेट के साथ सूचियों के लिए AsReference समर्थित नहीं है, इसलिए मैंने इस सीमा के लिए एक कामकाज का प्रयास किया है। मैंने सुपरलिस्ट नामक एक कस्टम सूची बनाई है जिसमें सुपरलिस्टइटम प्रकार की वस्तुओं में लिपटे आइटम निम्नानुसार हैं:

[ProtoContract]
public class SuperList<T> where T : class
{
    [ProtoMember(1)]
    private List<SuperListItem<T>> _items = new List<SuperListItem<T>>();

    public SuperList()
    {
    }

    public int IndexOf(T item)
    {
        int indexOf = -1;
        for (int index = 0; index < _items.Count; index++)
        {
            if (_items[index].Item == item)
            {
                indexOf = index;
                break;
            }
        }
        return indexOf;
    }

    public void Insert(int index, T item)
    {
        _items.Insert(index, new SuperListItem<T>(item));
    }

    public void RemoveAt(int index)
    {
        _items.RemoveAt(index);
    }

    public T this[int index]
    {
        get
        {
            return _items[index].Item;
        }
        set
        {
            _items[index] = new SuperListItem<T>(value);
        }
    }

    public void Add(T item)
    {
        _items.Add(new SuperListItem<T>(item));
    }

    public void Clear()
    {
        _items.Clear();
    }

    public bool Contains(T item)
    {
        bool contains = false;
        foreach (var listItem in _items)
        {
            if (listItem.Item == item)
            {
                contains = true;
                break;
            }
        }
        return contains;
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        for (int index = arrayIndex; index < _items.Count; index++)
            array[index] = _items[index].Item;
    }

    public int Count
    {
        get { return _items.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        SuperListItem<T> itemToRemove = null;
        foreach (var listItem in _items)
        {
            if (listItem.Item == item)
            {
                itemToRemove = listItem;
                break;
            }
        }
        if (itemToRemove != null)
            _items.Remove(itemToRemove);

        return itemToRemove != null;
    }

    public IEnumerator<T> GetEnumerator()
    {
        foreach(var listItem in _items)
            yield return listItem.Item;
    }
}

[ProtoContract]
public class SuperListItem<T>
{
    [ProtoMember(1, AsReference = true)]
    private readonly T _item;
    public T Item { get { return _item; } }

    private SuperListItem() { }

    public SuperListItem(T item)
    {
        _item = item;
    }
}

मेरे पास क्रमबद्धता के लिए निम्न परीक्षण कोड है:

[ProtoContract]
public class Thing
{
    [ProtoMember(1)]
    private readonly string _name;
    public string Name { get { return _name; } }

    private Thing() { }

    public Thing(string name)
    {
        _name = name;
    }
}

public class ProtoTest3
{
    public void Serialize()
    {
        SuperList<Thing> list = GetListOfThings();

        using (var fs = File.Create(@"c:\temp\things.bin"))
        {
            ProtoBuf.Serializer.Serialize(fs, list);

            fs.Close();
        }

        using (var fs = File.OpenRead(@"c:\temp\things.bin"))
        {
            list = ProtoBuf.Serializer.Deserialize<SuperList<Thing>>(fs);

            Debug.Assert(list[0] == list[2]);

            fs.Close();
        }
    }

    private SuperList<Thing> GetListOfThings()
    {
        var thing1 = new Thing("thing1");
        var thing2 = new Thing("thing2");

        var list = new SuperList<Thing>();
        list.Add(thing1);
        list.Add(thing2);
        list.Add(thing1);

        return list;
    }
}

हालांकि, जब मैं कोड चलाता हूं, तो मुझे अपवाद मिलता है "इस ऑब्जेक्ट के लिए कोई पैरामीटर रहित कन्स्ट्रक्टर परिभाषित नहीं किया गया है"। क्या यह केवल ProtoBuf.Net में एक सीमा है, या मैंने कुछ गलत किया है। क्या इस समस्या का कोई रास्ता है?

4
Simon Williams 8 सितंबर 2011, 16:02

1 उत्तर

सबसे बढ़िया उत्तर

स्पष्टीकरण देना; सूचियों की सीमा केवल यह है कि सूची ही को संदर्भ के रूप में नहीं माना जाता है। आइटम हैं, जब तक कि वे AsReference चिह्नित सदस्य पर हों - उदाहरण के लिए:

    [Test]
    public void SerializeTheEasyWay()
    {
        var list = GetListOfThings();

        using (var fs = File.Create(@"things.bin"))
        {
            ProtoBuf.Serializer.Serialize(fs, list);

            fs.Close();
        }

        using (var fs = File.OpenRead(@"things.bin"))
        {
            list = ProtoBuf.Serializer.Deserialize<MyDto>(fs);

            Assert.AreEqual(3, list.Things.Count);
            Assert.AreNotSame(list.Things[0], list.Things[1]);
            Assert.AreSame(list.Things[0], list.Things[2]);

            fs.Close();
        }
    }

    [ProtoContract]
    public class MyDto
    {
        [ProtoMember(1, AsReference = true)]
        public List<Thing> Things { get; set; }
    }

    private MyDto GetListOfThings()
    {
        var thing1 = new Thing("thing1");
        var thing2 = new Thing("thing2");

        var list = new List<Thing>();
        list.Add(thing1);
        list.Add(thing2);
        list.Add(thing1);

        return new MyDto {Things = list};
    }

(और मजेदार तथ्य - यह वास्तव में बिल्कुल तार पर समान है)

हालांकि, इस मामले में इंस्टेंस बनाने के तरीके के साथ एक बग प्रतीत होता है; यह .ctor का उपयोग कर रहा है और विफल हो रहा है। मैं इसकी जांच करूंगा और इसे ठीक करूंगा, हालांकि निम्नलिखित भी काम करते हैं:

1: पैरामीटर रहित .ctor सार्वजनिक करें:

        public Thing()
        {
        }

2: या वैकल्पिक रूप से, .ctor को अक्षम करें:

    [ProtoContract(SkipConstructor = true)]
    public class Thing
    { ...

मैं जांच करूंगा कि निजी पैरामीटर रहित निर्माता इस परिदृश्य में खुश क्यों नहीं हैं।

4
Marc Gravell 8 सितंबर 2011, 16:29
धन्यवाद मार्क, "थिंग" वर्ग पर निर्माता को सार्वजनिक करने से मेरी मूल समस्या हल हो गई है। मैंने मान लिया था कि कंस्ट्रक्टर त्रुटि सिर्फ AsReference का उप-उत्पाद था जो सूचियों के लिए उपलब्ध नहीं था (क्योंकि अगर मैंने AsReference को हटा दिया तो यह एक निजी कंस्ट्रक्टर के साथ काम करता था)।
 – 
Simon Williams
8 सितंबर 2011, 16:53
हाँ, यह उस मामले में वस्तु-निर्माण के साथ कुछ करना है।
 – 
Marc Gravell
8 सितंबर 2011, 17:04