2011-07-27 30 views
5

我使用的版本2 protobuf網的,目前我在歌廳錯誤「無法確定會員:A」是否允許在運行時ProtoBuf-net模型中使用<T>?

是否有可能當我們用ClassOfType創建protobuf網運行時模式< T>?如果是這樣,任何人都可以發現我在下面的代碼中缺少的東西嗎?

BTW:這個請求被建模斷Deserialize unknown type with protobuf-net我能得到一個版本這是怎麼回事就好了...但他們使用的是一個抽象基類,而不是一個泛型類T.

這是施工示例(不工作的東西被刪除)。

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() { } 
    } 
} 

請求

這是次要的,但它會是如果

(Container<SomeDerived>)model.DeserializeWithLengthPrefix(...) 

也可以實現這樣的

model.DeserializeWithLengthPrefix<Container<SomeDerived>>(...): 

BTW不錯:我開始深入protobuf網實施,我開始注意到一些像這樣的teresting方法。東西回來後,我想:

public MetaType Add(int fieldNumber, string memberName, Type itemType, Type defaultType); 

討論:

當我看見你可以反序列化在上面的鏈接的抽象基類的方式,我想,是的,這是接近在想什麼。我們是否可以首先反序列化到開放的通用容器<>,然後如果我們需要在不同的程序集中進行更具體的轉換。也許我在這裏混了一點。

你可以根據Tupple < TBase,TPayload>來考慮它。或者像Tupple < TBase,懶惰< TPayload >>也許。這與列表< T>沒有什麼不同。我也有一些TreeTypeThings,但我不需要序列化/反序列化它們(還)。

我有一個非通用的序列工作,所以它不是一個顯示塞。我的第一個實施可能會更有效率。儘管如此,我認爲我可以在現有的protobuf-net功能上做得更好。

我喜歡使用這些想法的更清潔的通用方法。儘管我可以手動到達相同的目的地,但泛型使其他事情成爲可能。

重:澄清

一切都可以被調用者提前定義。 (順便說一句:你讓我現在想着僅限於運行時的場景,但不,我不需要)。

+0

重新「無法確定成員:A「 - 這只是因爲*沒有名爲'A' *的成員,順便說一句。同樣地'B','C','D'或'E'。 –

+0

@Marc Gravell我會看看。我認爲* .Add(1,「A」)也創建了標籤。它不能那麼遠。說得通。哎呀。 – sgtz

+0

@Marc Gravell:我最終得到了一切正常工作+改變了上面的示例代碼來反映這一點。再次感謝。讓我們把開放的泛型看作是另一回事。 – sgtz

回答

4

所以我認爲這個問題歸結爲「我可以使用一個開放的泛型類型作爲protobuf模型的模板」,在這種情況下答案是「可能」。目前,它會看到BasicMsg<Foo>BasicMsg<Bar>爲不同的類型,它會默認使用屬性類型模型,因爲它不會將它們識別爲由[typeof(BasicMsg<>)]定義。如果他們屬性,它可能會工作,但我不認爲這是你的意圖,對吧?

這是一個有趣的場景,我很樂意討論它。然而,一個特別擔心我在這裏是在.NET中泛型的性質意味着這將需要運行時參與,即RuntimeTypeModel。我不認爲我可以通過預編譯TypeModel而不使用MakeGenericMethod,我真的想避免平臺和性能的原因。但是作爲完整的.NET運行時功能,它看起來很有趣。

(澄清以上;如果主叫方可以定義所有TBasicMsg<T>時間提前,它變得稍微更可行,那麼它真的可以歸結爲模型模板比喻)

+0

感謝您的關注。很親切。上面的評論,而不是試圖把它們納入推特x 3. – sgtz

+0

btw:評論現在在那裏。謝謝。 – sgtz

+0

是否可以序列化具有原始類型的對象?我已經嘗試了很多模型組合。順便說一句:你想這個請求作爲一個新問題嗎? – sgtz

相關問題