Estoy usando ServiceStack Redis. Tengo un struct y quiero almacenarlo en Redis. Pero cuando trato de obtenerlo, siempre devuelve el valor predeterminado. Pero si cambio el struct por class funciona bien . ¿Algunas ideas?

public struct PersonStruct
{
    public string Name { get; set; }
    public int Year { get; set; }
}

Prueba unitaria (siempre pasa, porque redis devuelve el valor predeterminado para la estructura)

var obj = new PersonStruct() {Name = "SomeName", Year = 1235};
_redis.Set(key, obj, TimeSpan.FromMinutes(2));
var result = _redis.Get<PersonStruct>(key);

Assert.AreEqual(default(PersonStruct), result);
1
satellite satellite 21 jul. 2020 a las 00:36

2 respuestas

La mejor respuesta

Para estructuras, debe usar serializador / deserializador personalizado

var obj = new PersonStruct() {Name = "SomeName", Year = 1235};
var bytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(obj));

_redis.Set(key, bytes, TimeSpan.FromMinutes(2));

var getBytes = _redis.Get(key);
var result = JsonSerializer.Deserialize<PersonStruct>(Encoding.UTF8.GetString(getBytes));

Parece que está serializando estructuras llamando a ToString()

2
Greg 20 jul. 2020 a las 23:30

Las diferencias con las de Struct es que son tratados como un solo escalar valor, donde en lugar de serializar cada propiedad de un valor de estructura, p. ej. Fecha, Día, DayOfWeek, DayOfYear, Hora, etc. en el caso de DateTime, solo se serializa un único valor escalar para DateTime's, TimeSpan's, etc.

ServiceStack.Text serializadores hace esto por convención donde intentará usar ToString() para serializar en un solo valor de cadena y el constructor TStruct(string) para deserializar el valor. Alternativamente, puede proporcionar su propia función de deserializador con un método estático ParseJson().

Entonces, si desea deserializar estructuras, necesitará proporcionar un serializador / deserializador para su Struct anulando ToString() y proporcionando un constructor de cadenas, por ejemplo:

public struct PersonStruct
{
    public PersonStruct(string jsonStr)
    {
        var str = jsonStr.FromJson<string>();
        Year = int.Parse(str.LeftPart(','));
        Name = str.RightPart(',');
    }
        
    public string Name { get; set; }
    public int Year { get; set; }
    
    public override string ToString() => Year + "," + Name;
}

Entonces podrá usarlo en ServiceStack.Redis Typed API como se ve en este ejemplo de Gistlyn gist .

2
mythz 21 jul. 2020 a las 06:30