使用Redis&存储从基类继承的类的集合。 C#

时间:2011-11-15 17:40:12

标签: c# redis servicestack event-store

我正在尝试使用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 个答案:

答案 0 :(得分:1)

您可以再次使用ServiceStack Redis客户端的最新版本(v3.05 +):

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 Unit Tests:)

相同
[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(); 
}