Raghav
Raghav

Reputation: 9630

Type is not expected, and no contract can be inferred with .NET predefined class with protobuf-net

I have a cache of collection of System.Globalization.CultureInfo class in my Context wrapper class

public Collection<System.Globalization.CultureInfo> Cultures
{
    get
    {
        // Get the value from Redis cache
    }
    set
    {
        // Save the value into Redis cache
    }
}

It can be accessed via MyContextWrapper.Current.Cultures.

I am getting the following error while serializing the value of "Collection Cultures" with protobuf-net:

Type is not expected, and no contract can be inferred: System.Globalization.CultureInfo

enter image description here

I am aware of the fact that protobuf-net needs [ProtoContract] and [ProtoMember] decoration on class but that is possible only for custom user defined classes.

How can I go with .NET predefined class then for example System.Globalization.CultureInfo in my case.

Is this even possible with protobuf-net?

Upvotes: 2

Views: 4191

Answers (1)

Measurity
Measurity

Reputation: 1346

You could go with a surrogate. Notify protobuf-net of it before you serialize the Collection. Though what I have now only works with the built-in cultures, you can extend it yourself to add addtional data to fully restore the culture back.

Example

The surrogate to convert CultureInfo into a protobuf-net supported type.

[ProtoContract]
public class CultureInfoSurrogate
{
    [ProtoMember(1)]
    public int CultureId { get; set; }

    public static implicit operator CultureInfoSurrogate(CultureInfo culture)
    {
        if (culture == null) return null;
        var obj = new CultureInfoSurrogate();
        obj.CultureId = culture.LCID;
        return obj;
    }

    public static implicit operator CultureInfo(CultureInfoSurrogate surrogate)
    {
        if (surrogate == null) return null;
        return new CultureInfo(surrogate.CultureId);
    }
}

Put this somewhere at the start of the program (at least before you are serializing the Collection):

RuntimeTypeModel.Default.Add(typeof(CultureInfo), false).SetSurrogate(typeof(CultureInfoSurrogate));

If you have further questions, let me know in the comments.

Upvotes: 3

Related Questions