我有一个用于表示身份的类,它包含一个字符串值。
然后我有另一个用于表示事件的类,包括一个标识对象和一个字符串名称。
我可以从对象序列化到JSON字符串,我得到字符串:
{"Id":{"Value":"2e4146c2-66c9-4637-8936-29ccfc5df638"},"Name":"Jon Doe"}
但是,当我从上面的JSON转到object时,在MyIdentity构造函数中,字符串identityValue作为"00000000-0000-0000-0000-000000000000"
传入。
我也试过为MyIdentity提供两个构造函数,一个用于字符串,一个用于Guid,但结果相同。这背后的想法是将数据存储为字符串,但要记住,如果需要,我们可以转换为Guid(因为身份将由字符串或Guid形成)。
public class MyEntityId : MyIdentity
{
public MyEntityId(Guid identityValue)
: base(identityValue)
{
}
}
public abstract class MyIdentity
{
protected readonly bool convertableAsGuid;
protected readonly string value;
public string Value { get { return this.value; } }
public MyIdentity(string identityValue)
{
this.value = identityValue;
Guid guid;
if(Guid.TryParse(identityValue, out guid)==false)
this.convertableAsGuid = false;
}
public MyIdentity(Guid identityValue)
{
this.value = identityValue.ToString();
this.convertableAsGuid = true;
}
}
static void Main(string[] args)
{
var evnt = new MyEvent(new MyEntityId(Guid.NewGuid()), "Jon Doe");
var eventHeaders = new Dictionary<string, object>
{
{"EventClrTypeName", evnt.GetType().AssemblyQualifiedName}
};
var serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None };
var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders, serializerSettings));
var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(evnt, serializerSettings));
string dataAsString = Encoding.UTF8.GetString(data);
var eventClrTypeName = JObject.Parse(Encoding.UTF8.GetString(metadata)).Property("EventClrTypeName").Value;
var obj = JsonConvert.DeserializeObject(dataAsString, Type.GetType((string)eventClrTypeName));
// stepping through the above, a zero initialised GUID string is passed in to MyIdentity constructor
}
正如@hvd友好地评论过,似乎只有一个get属性,如果我添加一个set属性,那么它就可以工作(所以我相信实际上并没有使用构造函数字符串值)。我不想在标识上加上setter的原因是编程设计,它是一个标识,一旦创建就不应该更改。
我可以使用属性上的公共get和protected设置,我尝试了关键字[JsonProperty]
并且它有效...但是我不想用这些属性装饰我的域对象 - 是否存在另一种方式?
答案 0 :(得分:1)
如果我理解正确,那么在反序列化时初始化Guid
并且您不想创建setter或使用属性来成功反序列化时会遇到问题。请注意,我通过删除接受MyIdentity
参数的构造函数来更改Guid
类,因为它没有必要,更改了Guid
逻辑的解析,因为它永远不会初始化convertableAsGuid
正确的属性并创建了MyEvent
类,因为你没有在你的问题上发布它。我还创建了在反序列化期间使用的MyCustomConverter
类。以下是课程:
public class MyCustomConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof (MyEvent);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
existingValue = new MyEvent(new MyEntityId(jObject["Id"]["Value"].ToString()), jObject["Name"].ToString());
return existingValue;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class MyEvent
{
public MyEntityId Id { get; set; }
public string Name { get; set; }
public MyEvent(MyEntityId id, string name)
{
Id = id;
Name = name;
}
}
public class MyEntityId : MyIdentity
{
public MyEntityId(string identityValue)
: base(identityValue)
{
}
}
public abstract class MyIdentity
{
protected readonly bool convertableAsGuid;
protected readonly string value;
public string Value { get { return this.value; } }
public MyIdentity(string identityValue)
{
this.value = identityValue;
Guid guid;
if (Guid.TryParse(identityValue, out guid))
this.convertableAsGuid = true;
}
}
这是序列化和反序列化逻辑:
static void Main(string[] args)
{
var evnt = new MyEvent(new MyEntityId(Guid.NewGuid().ToString()), "Jon Doe");
var eventHeaders = new Dictionary<string, object>
{
{"EventClrTypeName", evnt.GetType().AssemblyQualifiedName}
};
var serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None };
var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders, serializerSettings));
var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(evnt, serializerSettings));
string dataAsString = Encoding.UTF8.GetString(data);
var eventClrTypeName = JObject.Parse(Encoding.UTF8.GetString(metadata)).Property("EventClrTypeName").Value;
var obj = JsonConvert.DeserializeObject<MyEvent>(dataAsString, new JsonConverter[] {new MyCustomConverter()});
}