Question

J'écris un système qui a un ensemble de tampons de protocole (en utilisant protobuf-net), je veux définir quelque chose comme ça dans une classe abstraite tous hériteront de:

public byte[] GetBytes()

cependant, le serealiser tampon de protocole nécessite un argument de type, est-il un moyen efficace pour obtenir le type de la classe héritant?

Exemple:

public byte[] GetBytes()
    {
        using (MemoryStream stream = new MemoryStream())
        {
            Serializer.Serialize<T /* what goes here? */>(stream, this);
            return stream.ToArray();
        }
    }
Était-ce utile?

La solution

Il suffit d'écrire "T" droit?

puis dans votre déclaration de classe:

public class M<T>

- Modifier

Et puis quand vous héritez:

public class Foo : M<Apple>

Autres conseils

Vous pouvez le faire via la réflexion, mais protobuf-net fait pour vous.

Il suffit de changer votre appel à:

Serializer.NonGeneric.Serialize(stream, this /* Takes an object here */);

Cela fonctionne en construisant la méthode générique lors de l'exécution par réflexion. Pour plus de détails, consultez le code ( seconde méthode ).

Définissez votre classe de base comme BaseClass<T> et vos classes dérivées remplacent T avec le DerivedClass<SerializerType> type sérialiseur.

Vous pouvez également spécifier des contraintes sur l'argument de par exemple de type.

BaseClass<T> where T : SerializerBase

est une description de les types de contraintes que vous pouvez appliquer.

Vous n'avez pas fait quoi que ce soit de spécial ... puisque l'héritage respecte la protobuf-net. Si vous avez:

[ProtoInclude(typeof(Foo), 20)]
[ProtoInclude(typeof(Bar), 21)]
public abstract class MyBase {
    /* other members */

    public byte[] GetBytes()
    {
        using(MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize<MyBase>(ms, this); // MyBase can be implicit
            return ms.ToArray();
        }
    }
}
[ProtoContract]
class Foo : MyBase { /* snip */ }
[ProtoContract]
class Bar : MyBase { /* snip */ }

alors il fonctionnera. Pour sérialiser les données, il commence toujours à la base (contrat) de type ; même si vous avez fait Serializer.Serialize<Foo>(stream, obj) la première chose qu'il va faire est de détecter qu'il a une classe de base qui est un contrat, et passer à MyBase. Au cours de désérialisation il identifiera la bonne dérivée (béton) type et l'utiliser, vous pouvez donc utiliser Deserialize avec MyBase aussi, et il construira un Foo ou Bar en fonction de ce que les données d'origine était.

Ainsi, les éléments suivants sont en grande partie identiques:

Serializer.Serialize<BaseType>(dest, obj);
...
BaseType obj = Serializer.Deserialize<BaseType>(source);

et

Serializer.Serialize<DerivedType>(dest, obj);
...
DerivedType obj = Serializer.Deserialize<DerivedType>(source);

La principale différence est de savoir comment les variables sont typés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top