.net - protobuf-net WCF Multiple Nested Generic Abstract Objects Serialization v282 -


this first post on here, please bear me...

i'm trying nest multiple generic objects, , pass them through wcf using protobuf-net. there many (10+) main objects have implemented, tho code listed show 2. have similar structures, there few use 1 or 2 of generics (hence inheritance structure)

after working through tags , protoincludes, i've been able single main object serialize. when started working on next object, getting error:

known-type mainbase`2 protoincludeattribute must direct subclass of mainbase`1 

after racking brain few hours (and reading on here) got desperate , starting try random stuff. when removed protoinclude original main object , had them second one, worked fine!

in code below have tags still implemented can exception, if comment out either amain or bmain in 4 of mainbase classes, program able serialize whichever 1 tagged.

(i apologize in advance, code big large, haven't found problem complex mine yet)

class program {     static void main(string[] args)     {         var vcc = new amain();         var vccstream = new memorystream();         protobuf.serializer.serialize(vccstream, vcc);         vccstream.position = 0;         var newvcc = protobuf.serializer.deserialize<amain>(vccstream);           var vtc = new bmain();         var vtcstream = new memorystream();         protobuf.serializer.serialize(vtcstream, vtc);         vtcstream.position = 0;         var newvtc = protobuf.serializer.deserialize<bmain>(vtcstream);     } }  #region problem objects, 'main objects' base  [datacontract, protocontract, serializable] [protoinclude(2, typeof(amain))] [protoinclude(3, typeof(bmain))] public abstract class mainbase<tbbbase, tabase, tcbbase>     : mainbase<tbbbase, tabase>     tcbbase : cbbase     tbbbase : bbbase     tabase : abase {     [datamember, protomember(1)]     public tcbbase value3 { get; set; }      protected mainbase()     {         value3 = activator.createinstance(typeof(tcbbase)) tcbbase;     } }  [datacontract, protocontract, serializable] [protoinclude(2, typeof(mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase>))] [protoinclude(3, typeof(mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase>))] public abstract class mainbase<tbbbase, tabase>     : mainbase<tbbbase>     tbbbase : bbbase     tabase : abase {     [datamember, protomember(1)]     public tabase value2 { get; set; }      protected mainbase()     {         value2 = activator.createinstance(typeof(tabase)) tabase;     } }  [datacontract, protocontract, serializable] [protoinclude(2, typeof(mainbase<amainsub_bbbase, amainsub_abase>))] [protoinclude(3, typeof(mainbase<bmainsub_bbbase, bmainsub_abase>))] public abstract class mainbase<tbbbase> : mainbase     tbbbase : bbbase {     [datamember, protomember(1)]     public tbbbase value1 { get; set; }      protected mainbase()     {         value1 = activator.createinstance(typeof(tbbbase)) tbbbase;     } }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(mainbase<amainsub_bbbase>))] [protoinclude(2, typeof(mainbase<bmainsub_bbbase>))] public abstract class mainbase {     public abstract string mydefaultnamespace { get; } }  #endregion  #region main objects  [datacontract, protocontract, serializable] public class amain : mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase> {     public override string mydefaultnamespace { { return "videochunker"; } } }  [datacontract, protocontract, serializable] public class amainsub_bbbase : bbbbbase { }  [datacontract, protocontract, serializable] public class amainsub_abase : aabase { }  [datacontract, protocontract, serializable] public class amainsub_cbbase : cbbase { }   [datacontract, protocontract, serializable] public class bmain : mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase> {     public override string mydefaultnamespace { { return "videotranscoder"; } } }  [datacontract, protocontract, serializable] public class bmainsub_bbbase : bbbbbase { }  [datacontract, protocontract, serializable] public class bmainsub_abase : aabase { }  [datacontract, protocontract, serializable] public class bmainsub_cbbase : cbbase { }  #endregion  #region base objects  [datacontract, protocontract, serializable] [protoinclude(2, typeof(amainsub_bbbase))] [protoinclude(3, typeof(bmainsub_bbbase))] public abstract class bbbbbase : bbbbase { }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(bbbbbase))] public abstract class bbbbase : bbbase { }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(bbbbase))] public abstract class bbbase : bbase { public override string getconfignamespace { { return ".service"; } } }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(bbbase))] [protoinclude(2, typeof(cbbase))] public abstract class bbase : subbase { }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(amainsub_cbbase))] [protoinclude(2, typeof(bmainsub_cbbase))] public class cbbase : bbase { public override string getconfignamespace { { return ".fabric"; } } }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(bbase))] [protoinclude(4, typeof(abase))] public abstract class subbase { public virtual string getconfignamespace { { return string.empty; } } }  [datacontract, protocontract, serializable] [protoinclude(2, typeof(amainsub_abase))] [protoinclude(3, typeof(bmainsub_abase))] public abstract class aabase : abase { }  [datacontract, protocontract, serializable] [protoinclude(1, typeof(aabase))] public abstract class abase : subbase { public override string getconfignamespace { { return ".action"; } } }  #endregion 

since using older version of protobuf, decided pull down source , see if figure out. after bit of debugging found exception being thrown, , continue; instead of throwing exception.
in file serializert.cs, line 246 following:

foreach (protoincludeattribute pia in attribute.getcustomattributes(typeof(t), typeof(protoincludeattribute), false))             {                 type subclasstype = pia.resolveknowntype(typeof(t).assembly);                 if (subclasstype == null)                 {                     throw new protoexception("unable identify known-type protoincludeattribute: " + pia.knowntypename);                 }                 if (subclasstype.basetype != typeof(t))                 {                     continue;                     throw new protoexception(string.format(                         "known-type {0} protoincludeattribute must direct subclass of {1}",                         subclasstype.name, typeof(t).name));                 }                 property<t, t> prop;                 switch (pia.dataformat)                 {                     case dataformat.default:                         prop = (property<t, t>) propertyutil<t>.createtypedproperty("createpropertymessagestring", typeof(t), typeof(t), subclasstype);                         break;                     case dataformat.group:                         prop = (property<t, t>)propertyutil<t>.createtypedproperty("createpropertymessagegroup", typeof(t), typeof(t), subclasstype);                         break;                     default:                         throw new protoexception("invalid protoincludeattribute data-format: " + pia.dataformat);                 }                 // check duplicates                 if (tagsinuse.contains(pia.tag))                 {                     throw new invalidoperationexception(                         string.format("duplicate tag {0} detected in sub-type {1}", pia.tag, subclasstype.name));                 }                 tagsinuse.add(pia.tag);                 prop.init(pia.tag, pia.dataformat, propertyfactory.getpassthru<t>(), null, true, null);                 subclasslist.add(new keyvaluepair<type, property<t, t>>(subclasstype, prop));             } 

you can see continue' right above original throw. i'm not sure ramifications of action; actual bug or opening myself catastrophic craziness?

thanks time.

ok, think understand model (very glad didn't hard last night ;p) - have:

amain  : mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase>   : mainbase<amainsub_bbbase, amainsub_abase>    : mainbase<amainsub_bbbase> : mainbase  bmain  : mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase>   : mainbase<bmainsub_bbbase, bmainsub_abase>    : mainbase<bmainsub_bbbase> : mainbase  amainsub_bbbase, bmainsub_bbbase  : bbbbbase : bbbbase : bbbase : bbase : subbase amainsub_abase, bmainsub_abase  : aabase : abase : subbase amainsub_cbbase, bmainsub_cbbase  : cbbase : bbase : subbase 

this similar issue this question, , relates attributes generally, in attributes apply all closed types, not 1 thinking of. in particular, telling amain relates both mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase> and mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase> (and same crossovers there).

with 2 similar questions in short span, try , @ this, short-term think v2 modeller way fix this; have removed protoinclude attributes 3 generic types (mainbase<>, mainbase<,> , mainbase<,,>), then:

var model = runtimetypemodel.default;  model[typeof(mainbase<amainsub_bbbase>)].addsubtype(2, typeof(mainbase<amainsub_bbbase, amainsub_abase>)); model[typeof(mainbase<bmainsub_bbbase>)].addsubtype(2, typeof(mainbase<bmainsub_bbbase, bmainsub_abase>));  model[typeof(mainbase<amainsub_bbbase, amainsub_abase>)].addsubtype(2, typeof(mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase>)); model[typeof(mainbase<bmainsub_bbbase, bmainsub_abase>)].addsubtype(2, typeof(mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase>));  model[typeof(mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase>)].addsubtype(2, typeof(amain)); model[typeof(mainbase<bmainsub_bbbase, bmainsub_abase, bmainsub_cbbase>)].addsubtype(2, typeof(bmain)); 

(the regular attributes handle majority of cases)

note slight "feature" of since in parallel branches, don't need separate 2 / 3 tags, isn't expect either amain or bmain mainbase<amainsub_bbbase, amainsub_abase, amainsub_cbbase> - amain possible.

i have investigate options making cleaner - @ least in v2 can work!

re removing existing exception; don't believe v1 code has subtlety correctly handle scenario. removing exception cause fail in other interesting ways, in particular when tries work down type hierarchy. means make changes choose local copy, but: @ own risk - can't "yes safe", don't believe is. recommendation here use more sophisticated modelling in v2, while investigate ways of handling type of parallel generic model. changes here apply v2, v1 has no sane way of storing information, without introducing v2 type-modeller, i.e. making v1 v2.


Comments

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -