Frage

In den folgenden Beispielen:

public class RowData
{
    public object[] Values;
}

public class FieldData
{
    public object Value;
}

Ich bin gespannt, wie man entweder protobuf-net oder Dotnet-protobufs solcher Klassen behandeln würde. Ich bin mehr vertraut mit protobuf-net, also was ich eigentlich haben, ist:

[ProtoContract]
public class RowData
{
    [ProtoMember(1)]
    public object[] Values;
}
[ProtoContract]
public class FieldData
{
    [ProtoMember(1)]
    public object Value;
}

ich einen Fehler jedoch erhalten sagen: „Keine geeignete Standardobjektcodierung gefunden“. Gibt es eine einfache Möglichkeit, diese Klassen zu behandeln, dass ich einfach nicht bewusst?

Um mehr über den Anwendungsfall zu erarbeiten:

Dies ist eine abgespeckte Version einer Datenklasse in Remoting verwendet. So im Wesentlichen sieht es wie folgt aus:

FieldData data = new FieldData();
data.Value = 8;

remoteObject.DoSomething(data);

. Hinweis: Ich habe die ISerializable Umsetzung der Einfachheit halber weggelassen, aber es ist, wie man es erwarten würde

War es hilfreich?

Lösung

(aktualisiert)

rechts; ... über es heraus das Hauptproblem in meinem Beispiel war das Wert-Getter; sie Ausnahmen warfen. Es gab auch einige Bibliothek Glitches ( nun behoben ).

Allerdings ist der einfachste Ansatz ist Nullable<T> Pass-Thru-Eigenschaften:

    [ProtoMember(1)]
    private int? ValueInt32
    {
        get { return Get<int>(); }
        set { Value = value; }
    }

usw., mit:

    private T? Get<T>() where T : struct
    {
        return (Value != null && Value is T) ? (T?)Value : (T?)null;
    }

Dies und der * Angegebene Ansatz gewesen

Andere Tipps

Re protobuf-net, die wir halten:

Das Problem hier ist nicht wertTypen (die es oft feiner Griff) - es ist die offene object Nutzung, das heißt, sie einfach nicht wissen, welche Daten zu erwarten, und so, wie zu kodieren / dekodieren.

Im Moment kann ich nicht denken Sie an eine einfache / saubere Art und Weise, damit umzugehen. Es wird eine Reihe von gemeinsamem Wertetyp Szenarien, Listen und jede Ebene der Hierarchie behandelt basierend auf Verträge (Daten-Vertrag, proto-Verträgen oder einig XML-Schema), aber es braucht einen Hinweis .

Vielleicht, wenn Sie den Anwendungsfall klären können, könnte ich in der Lage sein, mehr zu helfen? Zum Beispiel würde die oben nicht funktioniert sehr mit DataContractSerializer oder XmlSerializer entweder ...

Re Dotnet-protobufs; Ich kann nicht wirklich sagen, aber ich bin ziemlich sicher, es wäre noch weniger nachsichtig; es ist beabsichtigt, mit Klassen aus einer .proto Datei generieren verwendet werden, so object würde einfach nie in das Modell eingeben (Jon: korrigiert mich wenn ich falsch bin)

.

Wenn Sie weitere Informationen zu tun lassen, könnten Sie bitte hier einen Kommentar hinterlassen? So kann ich es leicht finden ... Alternativ Sie mir eine Mail direkt (siehe mein SO Profil).


Bearbeiten - hier ist das Hacky, was ich im Sinne hatte - es nicht, im Moment arbeiten, aber ich werde herausfinden, warum morgen (wahrscheinlich). Beachten Sie, dass die zusätzlichen Mitglieder alle in der Theorie privat sein könnten - ich versuche nur, um es beim Debuggen einfach. Beachten Sie, dass dies keinen zusätzlichen Speicherplatz braucht. Wie ich schon sagte, es funktioniert nicht heute, aber es sollte - ich werde herausfinden, warum ...

[ProtoContract]
public class FieldData
{
    public object Value {get;set;}

    [ProtoMember(1)]
    public int ValueInt32 {
        get { return (int)Value; } set { Value = value; } }
    public bool ValueInt32Specified {
        get { return Value != null && Value is int; } set { } }

    [ProtoMember(2)]
    public float ValueSingle {
        get { return (float)Value; } set { Value = value; } }
    public bool ValueSingleSpecified {
        get { return Value != null && Value is float; } set { } }

    // etc for expected types
}

Das ist etwas, was ich im Sinn hatte. Lass mich wissen was du denkst. Natürlich würde ich eine Unterklasse für jeden Wert Typ hinzufügen muss ich unterstützen müssen. Was denkst du? Gibt es eine bessere Art und Weise, sehen Sie Ineffizienzen mit dieser Methode?

[ProtoContract, Serializable]
[ProtoInclude(1, typeof(Int32FieldData))]
public abstract class FieldDataBase : ISerializable
{
    [ProtoIgnore]
    public abstract object Value { get; set;}
    protected FieldDataBase()
    { }

    #region ISerializable Members
    protected FieldDataBase(SerializationInfo info, StreamingContext context)
    {
        Serializer.Merge<FieldDataBase>(info, this);
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Serializer.Serialize<FieldDataBase>(info, this);
    }

    #endregion
}

[ProtoContract, Serializable]
public class Int32FieldData : FieldDataBase
{
    [ProtoMember(1)]
    public int? Int32Value;

    [ProtoIgnore]
    public override object Value
    {
        get { return this.Int32Value.HasValue ? this.Int32Value : null; }
        set { this.Int32Value = (int?)value; }
    }
    public Int32FieldData() { }
    protected Int32FieldData(SerializationInfo info, StreamingContext context)
        :base(info, context)
    { }
}

Direkt Verkapselung scheint ohne zusätzlichen Aufwand von allen Eigenschaften, auf die folgende Weise zu funktionieren:

[ProtoContract, Serializable]
public class ObjectWrapper : ISerializable
{
    public ObjectWrapper()
    { }
    [ProtoIgnore]
    public object Value
    {
        get
        {
            if (Int32Value.HasValue)
                return Int32Value.Value;
            else if (BinaryValue != null)
                return BinaryValue;
            else
                return StringValue;
        }
        set
        {
            if (value is int)
                this.Int32Value = (int)value;
            else if (value is byte[])
                this.BinaryValue = (byte[])value;
            else if (value is string)
                this.StringValue = (string)value;
        }
    }
    [ProtoMember(1)]
    private int? Int32Value;
    [ProtoMember(2)]
    private string StringValue;
    [ProtoMember(3)]
    private byte[] BinaryValue;
            // etc

    #region ISerializable Members
    protected ObjectWrapper(SerializationInfo info, StreamingContext context)
    {
        Serializer.Merge<ObjectWrapper>(info, this);
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Serializer.Serialize<ObjectWrapper>(info, this);
    }

    #endregion
}
scroll top