Question

Dans les exemples suivants:

public class RowData
{
    public object[] Values;
}

public class FieldData
{
    public object Value;
}

Je suis curieux comment soit protobuf-net ou dotnet-protobufs traiterait ces classes. Je suis plus familier avec protobuf-net, donc ce que j'ai en fait est:

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

Cependant, je reçois une erreur « Aucun codage approprié par défaut de l'objet trouvé ». Est-il un moyen facile de traiter ces classes, que je ne suis pas au courant?

Pour élaborer davantage sur le cas d'utilisation:

Ceci est une version réduite d'une classe de données utilisées dans Remoting. Donc, essentiellement, il ressemble à ceci:

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

remoteObject.DoSomething(data);

Note:. J'ai omis la mise en œuvre ISerializable pour simplifier, mais il est comme vous attendez

Était-ce utile?

La solution

(mise à jour)

Droit; tout compris ... le principal problème dans mon échantillon était supérieure à la valeur arrivistes; ils ont jeté des exceptions. Il y avait aussi quelques problèmes de bibliothèque ( maintenant fixe).

Cependant, l'approche la plus simple est Nullable<T> pass-thru propriétés:

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

etc, avec:

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

Les deux cela et l'approche * spécifiées ont été

Autres conseils

Re protobuf-net, que je maintiens:

La question ici ne types de valeur (dont il sera souvent bien gérer) - il est l'utilisation de object ouverte, ce qui signifie qu'il ne sait tout simplement pas les données à attendre, et donc comment coder / décoder.

À l'heure actuelle, je ne peux pas penser à un moyen facile / propre pour gérer cela. Il traitera une série de scénarios de type valeur commune, les listes et tous les niveaux de la hiérarchie en fonction des contrats (données-contrat, proto-contrats, ou certains schémas XML), mais il a besoin d'un indice .

Peut-être que si vous pouvez préciser l'utilisation cas, je pourrais être en mesure d'aider plus? Par exemple, ce qui précède ne fonctionnerait pas très avec DataContractSerializer ou XmlSerializer soit ...

Re dotnet-protobufs; Je ne peux pas vraiment, mais je suis sûr que ce serait encore moins indulgent; il est destiné à être utilisé avec des classes générées à partir d'un fichier .proto, donc tout simplement jamais object n'entrer dans le modèle (Jon: corrigez-moi si je me trompe)

.

Si vous laissez plus d'informations, vous pouvez poster un commentaire bien voulu ici? Donc, je peux le trouver facilement ... Sinon, envoyez-moi directement un mail (voir mon profil SO).


modifier - voici la chose aki j'avais en tête - il ne fonctionne pas pour le moment, mais je vais comprendre pourquoi demain (probablement). Notez que, en théorie, les membres supplémentaires pourraient tous être privés - Je suis juste essayer de le rendre facile pendant le débogage. Notez que cela ne prend pas de stockage supplémentaire. Comme je le dis, cela ne fonctionne pas aujourd'hui, mais il devrait - je vais savoir pourquoi ...

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

Ceci est quelque chose comme ce que j'avais à l'esprit. Laissez-moi savoir ce que vous pensez. Naturellement, je dois ajouter une sous-classe pour chaque type de valeur que je dois soutenir. Qu'est-ce que tu penses? Y at-il une meilleure façon, vous voyez des inefficacités avec cette méthode?

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

encapsulation directe semble fonctionner très bien sans frais généraux supplémentaires de toutes les propriétés, de la manière suivante:

[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