2012-11-02 2 views
3

Я прочитал этот пост @mythz https://stackoverflow.com/a/12413091/1095655, но моя репутация не достаточно высока, чтобы комментироватьVersioning в ServiceStack - снова

У меня есть проблема, делая это работа. Если вы получаете запрос с версией DTO версии 1, версия отсутствует в переданных данных, потому что версия DTO версии 1 не имеет свойства Version. Когда ServiceStack десериализует запрос, он создает объект DTO (версия 3), с версией, установленной в 2, и поскольку версия не получена из переданных данных, версия не переустанавливается до 0, как и ожидалось. Как я вижу, вам нужно, чтобы версия была реализована с самого начала в вашем DTO, иначе это не сработает.

Надеюсь, я ошибаюсь, и кто-то может уточнить, что мне не хватает? Может ли это быть решено, поскольку у меня есть DTO в производстве без версии implememnted?

ответ

3

Да, это может быть сложно, когда вы впервые добавляете информацию Version, потому что вы хотите иметь номер версии в конструкторе, чтобы каждому вызову была назначена его неявная версия, в то же время тот же самый конструктор используется, когда вы deserialize в новый DTO.

К сожалению, поскольку в оригинальной DTO версии нет, она не сериализуется на проводе, поэтому никогда не отменяет неявно назначенное поле Version.

Чтобы обойти это (и сохранить неявно назначенный номер версии в конструкторе), вам необходимо эффективно сбросить версию, используемую при десериализации.

Вы можете сделать это с помощью сериализаторов JSON/JSV, переопределив JsConfig.ModelFactory на App_Start (то есть в AppConfig), который позволяет вам управлять экземпляром, созданным для каждого типа POCO, используемого при десериализации.

В этом случае мы хотим сбросить любой DTO, который имеет версию обратно 0 что путь DTOs без номера версии назначается 0 пока DTOS с номером версии будет переопределить его:

JsConfig.ModelFactory = type => { 
    if (typeof(IHasVersion).IsAssignableFrom(type)) 
    { 
     return() => { 
      var obj = (IHasVersion)type.CreateInstance(); 
      obj.Version = 0; 
      return obj; 
     }; 
    } 
    return() => type.CreateInstance(); 
}; 

Я используя явный интерфейс IHasVersion для простоты, но вы также можете легко использовать отражение для обнаружения и переназначения типов, содержащих номер версии.

Вот пример оригинального DTO без собственности Версии десериализации в DTO с неявно присвоенным номером версии:

public class Dto 
{ 
    public string Name { get; set; } 
} 

public interface IHasVersion 
{ 
    int Version { get; set; } 
} 

public class DtoV1 : IHasVersion 
{ 
    public int Version { get; set; } 
    public string Name { get; set; } 

    public DtoV1() 
    { 
     Version = 1; 
    } 
} 

Теперь, когда вы Deserialize оригинального DTO в новее DtoV1 это осталось как 0:

var dto = new Dto { Name = "Foo" }; 
var fromDto = dto.ToJson().FromJson<DtoV1>(); 
fromDto.Version // 0 
fromDto.Name // Foo 

И если вы используете новый DTO заселяет номер версии:

var dto1 = new DtoV1 { Name = "Foo 1" }; 
var fromDto1 = dto1.ToJson().FromJson<DtoV1>(); 
fromDto.Version // 1 
fromDto.Name // Foo 1 
+0

Условное решение. Спасибо, миф – BoKDamgaard