我在datacontract中有一个DateTime数据库。默认情况下,datacontractserializer将UTC时间序列化为yyyy-MM-ddTHH:mm:ss.fffffffZ
格式。我需要yyyy-MM-ddTHH:mm:ss.000Z
格式,但无法控制数据交换。那么我可以用DataContractSerializer做什么,它会以我想要的格式给我UTC时间。谢谢
答案 0 :(得分:4)
我创建了一个实现,它使用IDataContractSurrogate的实现来使用您拥有的DTO序列化DTO。
你没有提供DTO,所以我创建了一个作为你的原始DTO(你无法改变)和我们拥有的一个替代DTO。除了DateTime属性更改为String类型外,它们将具有相同的公共签名。
/// <summary>
/// original DTO, is fixed
/// </summary>
[DataContract]
class DTO
{
[DataMember]
public DateTime FirstDate { get; set; }
}
/// <summary>
/// Our own DTO, will act as surrogate
/// </summary>
[DataContract(Name="DTO")]
class DTO_UTC
{
[DataMember]
public string FirstDate { get; set; }
}
IDataContractSurrogate提供了在序列化和反序列化期间将一种类型替换为另一种类型所需的方法。
我在这里使用了简单的反思。如果需要更好的性能,请考虑在类型之间发出生成的代码,甚至生成目标类型。
public class DTOTypeSurrogate : IDataContractSurrogate
{
// this determines how you want to replace one type with the other
public Type GetDataContractType(Type type)
{
if (type == typeof(DTO))
{
return typeof(DTO_UTC);
}
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
// do we know this type
if (targetType == typeof(DTO))
{
// find each DateTime prop and copy over
var objType = obj.GetType();
var target = Activator.CreateInstance(targetType);
foreach(var prop in targetType.GetProperties())
{
// value comes in
var src = objType.GetProperty(prop.Name);
// do we need special handling
if (prop.PropertyType == typeof(DateTime))
{
DateTime utcConvert;
// parse to a datetime
if (DateTime.TryParse(
(string) src.GetValue(obj),
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.AdjustToUniversal,
out utcConvert))
{
// store
prop.SetValue(target, utcConvert);
}
}
else
{
// store non DateTime types
prop.SetValue(target, src);
}
}
return target;
}
return obj;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
// go from DTO to DTO_UTC
if (targetType == typeof(DTO_UTC))
{
var utcObj = Activator.CreateInstance(targetType);
var objType = obj.GetType();
// find our DateTime props
foreach(var prop in objType.GetProperties())
{
var src = prop.GetValue(obj);
if (prop.PropertyType == typeof(DateTime))
{
// create the string
var dateUtc = (DateTime)src;
var utcString = dateUtc.ToString(
"yyyy-MM-ddThh:mm:ss.000Z",
System.Globalization.CultureInfo.InvariantCulture);
// store
targetType.GetProperty(prop.Name).SetValue(utcObj, utcString);
} else
{
// normal copy
targetType.GetProperty(prop.Name).SetValue(utcObj, src);
}
}
return utcObj;
}
// unknown types return the original obj
return obj;
}
// omitted the other methods in the interfaces for brevity
}
这里我们创建DataContractSerializer并为其提供实例化的DTO,并在序列化之后反转该过程以检查结果是否相同。
var surrogateSerializer =
new DataContractSerializer(
typeof(DTO),
new Type[] {},
Int16.MaxValue,
false,
true,
new DTOTypeSurrogate()); // here we provide our own implementation
var ms = new MemoryStream();
// test data
var testDto = new DTO {
FirstDate = new DateTime(2015, 12, 31, 4, 5, 6, DateTimeKind.Utc) };
// serialize
surrogateSerializer.WriteObject(ms, testDto);
// debug
var wireformat = Encoding.UTF8.GetString(ms.ToArray());
//reset
ms.Position = 0;
//deserialize
var dtoInstance = (DTO) surrogateSerializer.ReadObject(ms);
// verify we have the same data returned
Debug.Assert(dtoInstance.FirstDate == testDto.FirstDate);