2011-06-30 4 views
2

オブジェクトProtoBuf-netを使用します。私が実装している主なオブジェクトは数多く(10+)あり、リストされているコードは2つしかありません。それらはすべて類似の構造を持っていますが、1つまたは2つのジェネリックしか使用しません(したがって継承構造)いるProtobufネットWCF複数のネストされた一般的な概要は、私が巣に複数の一般的なオブジェクトをしようとした後、WCFを介してそれらを通過してい</p> <p>...これがそう私と一緒に負担してください、ここでの私の最初の投稿ですシリアライゼーションv282

すべてのタグとProtoIncludesを処理した後、私はシリアル化する単一のメインオブジェクトを取得できました。数時間のために私の脳をラッキング(ここにアップ読んで)私は絶望的だ後

Known-type mainBase`2 for ProtoIncludeAttribute must be a direct subclass of mainBase`1 

といくつかのランダムなものをしようとし始めていた:私は、次のオブジェクトで作業し始めたとき、私はエラーを取得しました。元のメインオブジェクトのProtoIncludeを削除して2番目のオブジェクトのみを削除したところ、正常に機能しました!私はまだあなたが例外を得ることができるように実装されたすべてのタグを持って次のコードで

、あなたが mainBaseのすべてのクラス4に aMainまたは bMainのいずれかをコメントアウトした場合ただし、プログラムがある方1シリアライズすることができるようになります現在タグ付けされています。

(私は事前に謝罪、コードが大きい大きいですが、私はまだ私のような複雑な問題を発見していない)

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> 
    where TcbBase : cbBase 
    where TbbBase : bbBase 
    where TaBase : aBase 
{ 
    [DataMember, ProtoMember(1)] 
    public TcbBase Value3 { get; set; } 

    protected mainBase() 
    { 
     Value3 = Activator.CreateInstance(typeof(TcbBase)) as 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> 
    where TbbBase : bbBase 
    where TaBase : aBase 
{ 
    [DataMember, ProtoMember(1)] 
    public TaBase Value2 { get; set; } 

    protected mainBase() 
    { 
     Value2 = Activator.CreateInstance(typeof(TaBase)) as 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 
    where TbbBase : bbBase 
{ 
    [DataMember, ProtoMember(1)] 
    public TbbBase Value1 { get; set; } 

    protected mainBase() 
    { 
     Value1 = Activator.CreateInstance(typeof(TbbBase)) as 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 { get { 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 { get { 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 { get { 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 { get { return ".Fabric"; } } } 

[DataContract, ProtoContract, Serializable] 
[ProtoInclude(1, typeof(bBase))] 
[ProtoInclude(4, typeof(aBase))] 
public abstract class subBase { public virtual string GetConfigNamespace { get { 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 { get { return ".Action"; } } } 

#endregion 

私がいるProtobufの古いバージョンを使用しておりますので、私が決めましたそのソースをプルダウンして、何かを把握できるかどうかを確認してください。ちょっとしたデバッグの後、私は例外がスローされた場所を見つけました。例外をスローするのではなく、単にcontinue;を実行します。ファイルSerializerT.cs
、ライン246は以下の通りです:私のcontinue'は右オリジナルthrowの上にある場合

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 to identify known-type for ProtoIncludeAttribute: " + pia.KnownTypeName); 
       } 
       if (subclassType.BaseType != typeof(T)) 
       { 
        continue; 
        throw new ProtoException(string.Format(
         "Known-type {0} for ProtoIncludeAttribute must be a 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 for 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)); 
      } 

あなたが見ることができます。私は、この行動の結果がどのようなものであるか正確には分からない。これは実際のバグですか、私はいくつかの壊滅的な狂気まで自分自身を開いていますか?

お時間をいただきありがとうございます。 OK

+0

興味深い - ここは真夜中ですが、私は朝にこれを見ます –

+0

情報に関しては、v2では「A型は1つの継承階層(aMain)にしか参加できません」と失敗します - まだ調査中です –

答えて

0

は、私は今のモデルを理解すると思います(私は昨夜あまりにもハード見ていない非常に嬉しい; P) - あなたが持っている:

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 questionと同様の問題である、と関係します属性がに一般的にはで、属性がすべて閉鎖型に適用されます。特に、あなたは現在aMainは(すべてのクロスオーバーがあるためと同じ)両方mainBase<aMainSub_bbBase, aMainSub_aBase, aMainSub_cbBase>mainBase<bMainSub_bbBase, bMainSub_aBase, bMainSub_cbBase>に関連すること、それを言っています。

短い質問で2つの同様の質問がありましたが、私はこれを試してみますが、短期的にはv2モデラーがこれを修正する方法だと思います。私はその後、3つのジェネリック型(mainBase<>mainBase<,>mainBase<,,>)からProtoInclude属性を削除した:

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)); 

わずかな「機能」として

注意(通常の属性は、大多数の症例を扱います)これを我々は並列枝にあるため、それはあなたがからいずれかaMainまたはbMainを期待することはないとして、あなたは、別の2/3タグを必要としないこと- aMainのみ可能です。

このクリーナーを作成するためのオプションを調べる必要がありますが、少なくともv2では機能します。

既存の例外を削除し直してください。正直なところ、このシナリオを正しく処理するためにv1コードに微妙な要素があるとは思われません。その例外を削除すると、他の興味深い方法で失敗する可能性があります。特に型階層を解消しようとすると、失敗する可能性があります。是非、あなたのローカルコピーにあなたが選んだ変更を加えてください。それ自身のリスク - 私はそれが信じられないので、「安全です」と言うことはできません。ここでは、v2でより洗練されたモデリングを使用することをお勧めしますが、このタイプの並列ジェネリックモデルを処理する方法を調査します。基本的にv2型モデラーを導入することなく、すなわちv1をv2にすることなく、この情報を保存するための単純な方法はないため、ここでの変更はv2のみに適用されます。

関連する問題

 関連する問題