2012-04-06 1 views
1

У меня есть интерфейс и реализация, как с [ProtoContract]. Существует одно свойство, которое доступно только для чтения на интерфейсе. Когда я пытаюсь десериализации свойство, объявленное в качестве интерфейса, Protobuf дает мне эту ошибку:Могу ли я десериализовать свойство только для чтения интерфейса в protobuf-net?

System.InvalidOperationException: Cannot apply changes to property IFoo.Id

Вот код, я тестирую с:

public void Main() 
    { 
     using (var ms = new MemoryStream()) 
     { 
      var x = new HasFoo {TheFoo = new Foo(1)}; 

      Serializer.Serialize(ms, x); 
      ms.Position = 0; 
      var clone = Serializer.Deserialize<HasFoo>(ms); 

      Assert.AreEqual(1, clone.TheFoo.Id); 
     } 
    } 


    [ProtoContract, ProtoInclude(100, typeof(Foo))] 
    public interface IFoo 
    { 
     [ProtoMember(1)] 
     long Id { get; } 
    } 

    [ProtoContract] 
    public class Foo : IFoo 
    { 
     [ProtoMember(1)] 
     public long Id { get; private set; } 

     public Foo() { } 

     public Foo(long id) 
     { 
      Id = id; 
     } 
    } 

    [ProtoContract] 
    public class HasFoo 
    { 
     [ProtoMember(1)] 
     public IFoo TheFoo { get; set; } 
    } 

Я предпочел бы не объявить setter на интерфейсе, и я хотел бы сохранить свойство TheFoo, объявленное как IFoo, если это вообще возможно. Есть ли способ, которым можно заставить работать? Я использую protobuf-net v2.

+0

Нет, вы не можете, объект сконструирован и, таким образом, отсутствует возможность использовать ваш частный набор. – Landern

ответ

4

№ При привязке к интерфейсу он привязывается к интерфейсу, поэтому он не может использовать какие-либо частные сеттеры (и т. Д.), Которые будут доступны при привязке к конкретному типу. Единственный способ сделать это - рекламировать членов Foo для сериализации вместо IFoo.

Примечание: в сценариях без интерфейса он будет иметь доступ к членам или даже к прямому полю желаемого.