23

私はこの回答を調べましたが、下位互換性を維持する必要がなく、protobuf-netに必要な属性で数十のクラスを装飾しなくても機能するソリューションが必要な状況にあります。使用してみRuntimeTypeModel.Default.InferTagFromNameDefault = true;ましたが、Serializer.Serialize呼び出しでコントラクトを要求する例外がスローされるため、正しく使用されていない可能性があります。これが私の簡単なテストです、私は何が間違っているのですか?

public enum CompanyTypes
{
    None, Small, Big, Enterprise, Startup
}

public class BaseUser
{
    public string SSN { get; set; }    
}

public class User : BaseUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public DateTime BirthDate { get; set; }
    public List<string> Friends { get; set; }
    public Company Company { get; set; }
}

public class Company
{
    public string Name { get; set; }
    public string Address { get; set; }
    public CompanyTypes Type { get; set; }
    public List<Product> Products { get; set; }
}

public class Product
{
    public string Name { get; set; }
    public string Sku { get; set; }
}

[TestClass]
public class SerializationTest
{
    [TestMethod]
    public void SerializeDeserializeTest()
    {
        var user = new User
                       {
                           Age = 10,
                           BirthDate = DateTime.Now.AddYears(-10),
                           FirstName = "Test First",
                           LastName = "Test Last",
                           Friends = new List<string> { "Bob", "John" },
                           Company = new Company
                                         {
                                             Name = "Test Company",
                                             Address = "Timbuktu",
                                             Type = CompanyTypes.Startup,
                                             Products = new List<Product>
                                             {
                                                new Product{Name="Nerf Rocket", Sku="12324AC"},
                                                new Product{Name="Nerf Dart", Sku="DHSN123"}
                                             }
                                         }
                       };

        RuntimeTypeModel.Default.InferTagFromNameDefault = true;
        using (var memoryStream = new MemoryStream())
        {
            Serializer.Serialize(memoryStream, user);
            var serialized = Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
        }
    }
}
4

3 に答える 3

29

InferTagFromName(そしてそれは双子です)メンバーのタグ番号InferTagFromNameDefaultを解決する必要がある場合にのみ手を取ります。それらは、どのメンバーをシリアライズする必要があるかに影響を与えません (したがって、システムがそれらについて知っていたとしても、現在の答えは: なしです)。選択した可能性のあるオプションは ですが、これは現在マーカーとしてのみ使用できます。少しの注釈を気にしない場合、実用的な修正は次のとおりです。ImplicitFields[ProtoContract(...)]

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]

on UserCompanyand Product、および for のもう少し複雑なものBaseUser(継承のため):

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic, ImplicitFirstTag = 10)]
[ProtoInclude(1, typeof(User))]

メンバーごとに多くの注釈を追加する必要がないことに注意してください。あなたが本当に反属性である場合は、次の方法でコードを介してモデル全体を構成することもできます。

RuntimeTypeModel.Default.Add(typeof(Product), false).Add("Name", "Sku");
RuntimeTypeModel.Default.Add(typeof(Company), false).Add("Name", "Address",
         "Type", "Products");
RuntimeTypeModel.Default.Add(typeof(User), false).Add("FirstName", "LastName",
         "Age", "BirthDate", "Friends", "Company");
RuntimeTypeModel.Default.Add(typeof(BaseUser), false).Add(10, "SSN")
         .AddSubType(1, typeof(User));
于 2012-09-07T06:20:36.023 に答える
3

この段階では非常に実験的ですが、ほとんどのタイプを取り、実行時に Protobuf-net シリアライザーを生成する小さなライブラリを作成しました: https://github.com/fnicollier/AutoProtobuf

于 2015-01-09T13:05:33.140 に答える