estoy usando la versión 2 de protobuf-net, y actualmente estoy que consigue el error "No se puede determinar miembro de: Un"¿Está permitido el <T> en un modelo ProtoBuf-net en tiempo de ejecución?
¿Es posible crear un modelo de tiempo de ejecución para Protobuf-net cuando usamos ClassOfType < T>? Si es así, ¿alguien puede detectar lo que me falta en el código siguiente?
por cierto: esta solicitud se modela fuera de Deserialize unknown type with protobuf-net que pude conseguir una versión de esta yendo muy bien ... pero que están utilizando una clase base abstracta, no una clase genérica de T.
ESTE ES UN TRABAJO EJEMPLO (las cosas que no funcionaban se eliminan).
using System;
using System.IO;
using NUnit.Framework;
using ProtoBuf;
using ProtoBuf.Meta;
namespace ProtoBufTestA2
{
[TestFixture]
public class Tester
{
[Test]
public void TestMsgBaseCreateModel()
{
var BM_SD = new Container<SomeDerived>();
using (var o = BM_SD) {
o.prop1 = 42;
o.payload = new SomeDerived();
using (var d = o.payload) {
d.SomeBaseProp = -42;
d.SomeDerivedProp = 62;
}
}
var BM_SB = new Container<SomeBase>();
using (var o = BM_SB) {
o.prop1 = 42;
o.payload = new SomeBase();
using (var d = o.payload) {
d.SomeBaseProp = 84;
}
}
var model = TypeModel.Create();
model.Add(typeof(Container<SomeDerived>), true); // BM_SD
model.Add(typeof(Container<SomeBase>), true); // BM_SB
model.Add(typeof(SomeBase), true); // SB
model.Add(typeof(SomeDerived), true); // SD
model[typeof(SomeBase)].AddSubType(50, typeof(SomeDerived)); // SD
var ms = new MemoryStream();
model.SerializeWithLengthPrefix(ms, BM_SD, BM_SD.GetType(), ProtoBuf.PrefixStyle.Base128, 0);
model.SerializeWithLengthPrefix(ms, BM_SB, BM_SB.GetType(), ProtoBuf.PrefixStyle.Base128, 0);
ms.Position = 0;
var o1 = (Container<SomeDerived>)model.DeserializeWithLengthPrefix(
ms
, null
, typeof(Container<SomeDerived>), PrefixStyle.Base128, 0);
var o2 = (Container<SomeBase>)model.DeserializeWithLengthPrefix(
ms
, null
, typeof(Container<SomeBase>), PrefixStyle.Base128, 0);
}
}
[ProtoContract]
public class Container<T> : IDisposable
{
[ProtoMember(1)]
public int prop1 { get; set; }
[ProtoMember(2)]
public T payload { get; set; }
public void Dispose() { }
}
[ProtoContract]
public class AnotherDerived : SomeDerived, IDisposable
{
[ProtoMember(1)]
public int AnotherDerivedProp { get; set; }
public override void Dispose() { }
}
[ProtoContract]
public class SomeDerived : SomeBase, IDisposable
{
[ProtoMember(1)]
public int SomeDerivedProp { get; set; }
public override void Dispose() { }
}
[ProtoContract]
public class SomeBase : IDisposable
{
[ProtoMember(1)]
public int SomeBaseProp { get; set; }
public virtual void Dispose() { }
}
[ProtoContract]
public class NotInvolved : IDisposable
{
[ProtoMember(1)]
public int NotInvolvedProp { get; set; }
public void Dispose() { }
}
[ProtoContract]
public class AlsoNotInvolved : IDisposable
{
[ProtoMember(1)]
public int AlsoNotInvolvedProp { get; set; }
public void Dispose() { }
}
}
Solicitud
Ésta es menor, pero sería bueno si
(Container<SomeDerived>)model.DeserializeWithLengthPrefix(...)
también podrían implementarse como esto
model.DeserializeWithLengthPrefix<Container<SomeDerived>>(...):
por cierto: estoy comenzando a profundizar en la implementación de protobuf-net, y estoy empezando a notar algunos en métodos de investigación como este. Algo para volver a tarde supongo:
public MetaType Add(int fieldNumber, string memberName, Type itemType, Type defaultType);
Discusión:
cuando vi la forma en que podría deserializar a un tipo de base abstracta en el enlace anterior, pensé, sí, eso es más cerca de que estaba pensando Podríamos deserializar al contenedor genérico abierto <> primero, y luego emitirlo más específicamente si lo necesitamos en diferentes ensamblajes. Quizás me estoy confundiendo un poco aquí.
Se podría pensar en términos de Tupple < TBase, TPayload>. O una variación como Tupple < TBase, Lazy < TPayload >> maybe. No es tan diferente a la lista < T>. Hay algunos TreeTypeThings < T> que tengo también, pero no necesito serializarlos/deserializarlos (todavía).
Tenía una secuencia no genérica funcionando, por lo que no es un stopper. Mi primera implementación podría ser más eficiente. Creo que puedo hacerlo mejor con las funciones existentes de protobuf-net.
Me gusta la manera más limpia de trabajar con estas ideas. Aunque puedo llegar al mismo destino manualmente, los genéricos hacen que otras cosas sean posibles.
re: aclaración
todo puede ser definido de antemano por la persona que llama. (Por cierto: ahora me tienes pensando en el escenario de tiempo de ejecución, pero no, no lo necesito).
Re "No se puede miembro de determinar : A "- eso es simplemente porque * no hay ningún miembro llamado' A' *, por cierto. Del mismo modo 'B',' C', 'D' o' E'. –
@Marc Gravell Voy a ver eso. Yo * pensé * que .Add (1, "A") también creó la etiqueta. No puede llegar tan lejos. Tiene sentido. Oops. – sgtz
@Marc Gravell: Todo funcionó bien al final + cambié el código de ejemplo anterior para reflejar esto. Gracias de nuevo. Dejemos los genéricos abiertos como algo para mirar en otro momento. – sgtz