Domanda

Sto scrivendo un sistema che ha una serie di buffer di protocollo (usando protobuf-net), voglio definire qualcosa di simile in una classe astratta da cui tutti ereditano:

public byte[] GetBytes()

tuttavia, il serializzatore del buffer di protocollo richiede un argomento di tipo, esiste un modo efficiente per ottenere il tipo della classe ereditaria?

Esempio:

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

Soluzione

Basta scrivere "T", giusto?

e poi nella dichiarazione di classe:

public class M<T>

- Modifica

E poi, quando si eredita esso:

public class Foo : M<Apple>

Altri suggerimenti

È possibile farlo attraverso la riflessione, ma protobuf-net ha fatto per voi.

Basta cambiare la chiamata a:

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

Questo funziona con la costruzione del metodo generico a runtime attraverso la riflessione. Per i dettagli, controllare il codice (secondo metodo qui ).

Definire la classe di base come BaseClass<T> e quindi i vostri classi derivate sostituire T con il tipo serializzatore DerivedClass<SerializerType>.

È inoltre possibile specificare i vincoli sul tipo di argomento per es.

BaseClass<T> where T : SerializerBase

Qui è una descrizione di è possibile applicare i tipi di vincoli.

In realtà non hai bisogno di niente di speciale qui...poiché protobuf-net rispetta l'ereditarietà.Se hai:

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

allora funzionerà.Per serializzare i dati, it inizia sempre dal tipo base (contratto).;quindi anche se lo facessi Serializer.Serialize<Foo>(stream, obj) la prima cosa che farà è rilevare che ha una classe base che è un contratto e passare a essa MyBase.Durante la deserializzazione identificherà il tipo derivato (concreto) corretto e lo utilizzerà, in modo da poterlo utilizzare Deserialize con MyBase anche, e costruirà a Foo O Bar a seconda di quali fossero i dati originali.

Pertanto i seguenti sono in gran parte identici:

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

E

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

La differenza principale qui è il modo in cui vengono digitate le variabili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top