Хранение коллекции классов, которые наследуются от базового класса с использованием Redis & C # - PullRequest
1 голос
/ 15 ноября 2011

Я пытаюсь создать простое хранилище событий, используя C # и [ServiceStack] Redis.

public class AggregateEvents
{
    public Guid Id { get; set;}
    public List<DomainEvent> Events { get; set; }
}

public abstract class DomainEvent { }

public class UserRegisteredEvent : DomainEvent 
{
    public Guid UserId { get; set; }
    public string Name { get; set; }
}

public class UserPromotedEvent : DomainEvent
{
    public Guid UserId { get; set; }
    public string NewRole { get; set; }
}

если я сделаю roots.GetAll(), я получу исключение, потому что абстрактный класс не может быть создан. Если вместо этого я превращу базовый класс в интерфейс, объект Events будет иметь значение null, и объекты, которые я там храню, будут потеряны.

Есть мысли?

Редактировать 1

Нет радости, используя v3.03 и этот код:

    [Test]
    public void foo()
    {
        var client = new RedisClient("localhost");
        var users = client.GetTypedClient<AggregateEvents>();


        var userId = Guid.NewGuid();

        var eventsForUser = new AggregateEvents
                       {
                           Id = userId,
                           Events = new List<DomainEvent>()
                       };

        eventsForUser.Events.Add(new UserPromotedEvent { UserId = userId });


        users.Store(eventsForUser);

        var all = users.GetAll(); // exception
    }

Редактировать 2

Также не работает с этим подходом;

    [Test]
    public void foo()
    {
        var userId = Guid.NewGuid();
        var client = new RedisClient("localhost");

        client.As<DomainEvent>().Lists["urn:domainevents-" + userId].Add(new UserPromotedEvent {UserId= userId});


        var users = client.As<DomainEvent>().Lists["urn:domainevents-" + userId];

        foreach (var domainEvent in users) // exception
        {

        }
    }

1 Ответ

1 голос
/ 15 ноября 2011

Можете ли вы попробовать еще раз с последней версией (v3.05 +) клиента ServiceStack Redis:

https://github.com/ServiceStack/ServiceStack.Redis/downloads

ServiceStack Json Serializer, который использует клиент, только что добавил поддержкудля десериализации абстрактных / интерфейсных типов, которые будут в последней версии клиента.

Примечание: это работает путем встраивания информации __ type в полезную нагрузку JSON, которая сообщает сериализатору, какой конкретный класс этоследует десериализовать в.Эта информация встраивается только для типов Abstract / interface / object.Таким образом, при сериализации вам необходимо привести к абстрактному типу, например:

redis.Store((DomainEvent)userPromoEvent);

или при добавлении в список:

redis.As<DomainEvent>().Lists["urn:domainevents"].Add(userPromoEvent);

Эти примеры теперь работают, как указанонедавно добавленные модульные тесты DomainEvents :)

[Test]
public void Can_Retrieve_DomainEvents()
{
    var userId = Guid.NewGuid();
    var client = new RedisClient("localhost");
    client.FlushAll();

    client.As<DomainEvent>().Lists["urn:domainevents-" + userId].Add(
        new UserPromotedEvent { UserId = userId });

    var users = client.As<DomainEvent>().Lists["urn:domainevents-" + userId];

    Assert.That(users.Count, Is.EqualTo(1));

    var userPromoEvent = (UserPromotedEvent)users[0];
    Assert.That(userPromoEvent.UserId, Is.EqualTo(userId));
}


[Test]
public void Can_from_Retrieve_DomainEvents_list()
{
    var client = new RedisClient("localhost");
    var users = client.As<AggregateEvents>();

    var userId = Guid.NewGuid();

    var eventsForUser = new AggregateEvents
    {
        Id = userId,
        Events = new List<DomainEvent>()
    };

    eventsForUser.Events.Add(new UserPromotedEvent { UserId = userId });

    users.Store(eventsForUser);

    var all = users.GetAll(); 
}
...