问题
I have a Windows Phone 7 project that connects to a .NET web service to fetch data on demand. Both the WP7 project and the web service use a copy of the same c# class library. Part of this library is an enum of EmployeeType
:
Public enum EmployeeType
{
Standard = 0,
TeamLeader = 105
}
Since the app was released, the web service class library has had a change made to it - adding a new enum value. (SeniorManager = 110
)
Therefore, when I receive an object on the phone with a property containing the new enum value, I get a SerializationException
when attempting to add it to IsolatedStorage. This is because the new enum value cannot be serialized, as the WP7 class library has not had the same update made to it and the enum value does not exist.
What I would like to achieve is to still be able to serialize the object, but ignore the invalid enum value, or replace it with a valid one (ideally Standard = 0
).
This will enable me to handle any future additions made to the web service enum, without breaking the functionality of the app.
Notes:
- The enum/values above are contrived for the purposes of the question and not the actual enum in question.
- The fact that the value would be serialized with an incorrect value is unimportant for the purposes of the app.
Thanks!
回答1:
I ended up using JSON.NET to deserialize the data from the server (reader
is a StreamReader
for the response stream. TResponse
is the generic response expected from the server.):
var serializer = new JsonSerializer();
serializer.Converters.Add(new JsonEnumTypeConverter());
this.Response = serializer.Deserialize<TResponse>(new JsonTextReader(reader));
The JsonEnumTypeConverter
class checks that the enum value returned from the server is valid for the given type. If not, then it's defaulted to zero. (Always present on enums). This class is defined as follows:
private class JsonEnumTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
var value = Enum.Parse(objectType, reader.Value.ToString(), true);
if (IsFlagDefined((Enum)value))
{
return value;
}
else
{
return 0;
}
}
catch (Exception)
{
return 0;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
private static bool IsFlagDefined(Enum e)
{
decimal d;
return (!decimal.TryParse(e.ToString(), out d));
}
}
Note that I use the custom IsFlagDefined
method, rather than Enum.IsDefined
as my enums include [Flags] attributes which Enum.IsDefined
does not handle. (Source: Enum.IsDefined with flagged enums)
Also, credit to Darin Dimitrov's answer in this question for pointing me towards JSON.NET and the JsonConverter.
回答2:
I don't understand why you don't update the reference to the WebService in WP7 project, so that you will be able to serialize it.
Anyway, you can try this workaorund:
The real field, not to be serialized
[NonSerialized] public EmployeeType RealType {get; set;}
A fake field, that will be serialized returns Standard if Realfield is SeniorManager or actual RealField value
public EmployeeType Type { get{ if (RealType== EmployeeType.TeamLeader) return EmployeeType.TeamLeader; else return EmployeeType.Standard; } set{RealType=value;} }
来源:https://stackoverflow.com/questions/9974127/serializing-object-with-invalid-enum-value