Сериализация времени UTC c#

у меня есть datetime datamember в datacontract. По умолчанию datacontractserializer сериализует время UTC до . Мне это нужно в yyyy-MM-ddTHH:mm:ss.000Z формат, но не имеют контроля над datacontracts. Так что я могу сделать с DataContractSerializer, который дал бы мне время UTC в формате, который я хочу. Спасибо

1 ответов


Я создал реализацию, которая использует реализацию IDataContractSurrogate для сериализации ваших DTO с DTO, которыми вы владеете.

ДТО это

вы не предоставили DTO, поэтому я создал один, чтобы быть вашим оригинальным DTO (который вы не можете изменить) и одной заменой DTO, которой мы владеем. Они будут иметь одинаковую общедоступную подпись, за исключением того, что их свойства DateTime изменяются на строковые типы.

/// <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

В 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);