Domanda

Negli esempi seguenti:

public class RowData
{
    public object[] Values;
}

public class FieldData
{
    public object Value;
}

Sono curioso di sapere come protobuf-net o dotnet-protobufs gestirebbero tali classi.Ho più familiarità con protobuf-net, quindi quello che ho effettivamente è:

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

Tuttavia ricevo un errore che dice "Nessuna codifica oggetto predefinita adatta trovata".Esiste un modo semplice per trattare queste classi, di cui non sono a conoscenza?

Per approfondire il caso d'uso:

Questa è una versione ridotta di una classe di dati utilizzata nella comunicazione remota.Quindi essenzialmente assomiglia a questo:

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

remoteObject.DoSomething(data);

Nota:Ho omesso l'implementazione ISerializable per semplicità, ma è come ti aspetteresti.

È stato utile?

Soluzione

(aggiornato)

A destra; capito ... il problema principale nel mio esempio sopra riportato è stato il valore-getter; stavano gettando le eccezioni. C'erano anche alcuni difetti di libreria ( ora risolto ).

Tuttavia, l'approccio più semplice è Nullable<T> pass-thru proprietà:

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

ecc, con:

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

Sia questo e l'approccio * specificati sono stati testato , e ora funziona bene.

Altri suggerimenti

Re protobuf-net, che mantengo:

Il problema qui non sono i tipi di valore (che spesso gestiranno bene): è l'open object utilizzo, il che significa semplicemente che non sa quali dati aspettarsi e quindi come codificarli/decodificarli.

Al momento, non riesco a pensare a un modo semplice/pulito per gestirlo.Gestirà una serie di scenari comuni di tipo valore, elenchi e qualsiasi livello di gerarchia basata su contratti (contratto dati, proto-contratti o alcuni schemi xml), ma necessita di un traccia.

Forse se puoi chiarire il caso d'uso, potrei essere in grado di aiutarti di più?Ad esempio, quanto sopra non funzionerebbe molto con DataContractSerializer O XmlSerializer O...

Re dotnet-protobufs;Non posso davvero commentare, ma sono abbastanza sicuro che sarebbe ancora meno indulgente;è pensato per essere utilizzato con classi generate da un file .proto, quindi object semplicemente non entrerebbero mai nel modello (Jon:correggetemi se sbaglio).

Se lasci maggiori informazioni, potresti gentilmente postare un commento qui?Quindi posso trovarlo facilmente...In alternativa, mandami una mail direttamente (vedi il mio profilo SO).


modifica - ecco la cosa hack che avevo in mente - non funziona al momento, ma capirò il perché domani (probabilmente).Tieni presente che in teoria i membri extra potrebbero essere tutti privati: sto solo cercando di semplificarlo durante il debug.Tieni presente che ciò non richiede spazio di archiviazione aggiuntivo.Come ho detto, oggi non funziona, ma dovrebbe... scoprirò perché...

[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
}

Questo è qualcosa di simile a quello che avevo in mente. Fatemi sapere cosa ne pensate. Naturalmente avrei dovuto aggiungere una sottoclasse per ogni tipo di valore che ho bisogno di sostegno. Cosa ne pensi? C'è un modo migliore, non si vede alcun inefficienze con questo metodo?

[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)
    { }
}

incapsulamento diretto sembra funzionare bene senza alcun overhead aggiuntivo da tutte le proprietà, nel seguente modo:

[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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top