4

我的应用程序中(几乎)所有 POCO 类都有一个主基类。

public abstract class AceOfBase
{
    public long Id { get; set; }
    public DateTimeOffset CreatedOn { get; set; }
    public string Key { get; set; }
}

我的一些主要类(Member , Building, Community, etc.)具有相当多的属性,因此我计划利用ServiceStack 的 强类型客户端提供的简单管理。

从我所做的研究来看,客户似乎使用结构化的方法来创建密钥

本质上,POCO 以序列化 JSON 的形式存储到 Redis 中,其中 typeof(Poco).Name 和 Id 用于形成该实例的唯一键。例如:

瓮:Poco:{Id} => '{"Id":1,"Foo":"Bar"}'

因为有时我会检索一个继承基类的对象(但我在编译时不知道派生类)我怎样才能最好地存储密钥以便我可以轻松获取任何对象?

一个理想的世界,我将能够配置RedisClientRedisTypedClient使用相同的密钥命名约定,但我还没有找到任何可以让我这样做的东西(还),而且对于两个客户来说,关于单个方法的文档都很难获得。

4

1 回答 1

1

在挖掘了ServiceStack程序集之后,我发现强类型客户端的Store()方法实际上只是SetEntry(key,value)一个用于生成密钥结构的实用程序方法。

该实用程序方法IdUtils.CreateUrn有一些重载,可让您指定Type然后Id返回用作键的字符串。

然后,我所做的是CreateKey在我的 Repository 基类中编写一个方法,然后在AceOfBase创建任何对象时调用该方法并将其设置为Key.

//In BaseRepository
public virtual string CreateKey<T>(T entity) where T : AceOfBase
{
 return IdUtils.CreateUrn<AceOfBase>(entity.Id);
}

//In MemberRepository
Member m = new Member(); //inherits from AceOfBase
m.Key = CreateKey(m);

我还在我的应用程序中实现了两组类,它们帮助我利用 Redis 疯狂的快速查询时间,同时允许我像使用 EF 一样正常使用关系。

  1. DomainModels——这些看起来像普通的类,因为它们的属性是传统的结构化的。

    public class Activity : AceOfBase
    {
        public AceOfBase IndirectObject { get; set; }
        public Participant Predicate { get; set; }
        public Participant Subject { get; set; }
        public Verb Verb { get; set; }
    }
    
  2. DataModels——它们包含与其对应的 DomainModel 相同的原语和枚举,但如果一个字段是存储在 Redis 中的自定义类型,则它被替换为代表该对象键的字符串(具有相同的属性名称)。

    public class Activity : AceOfBase
    {
        public string IndirectObject { get; set; }
        public string Predicate { get; set; }
        public string Subject { get; set; }
        public Verb Verb { get; set; }
    }
    

我已经AutoMapper使用一组自定义TypeConverter类实现了将DataModel字符串属性转换为DomainModel. AutoMapper然后在存储任何对象之前以及从 Redis 中提取对象并在两种模型类型之间转换之后立即调用。

//In Configure()
Mapper.CreateMap<string,Member>().ConvertUsing<KeyToBaseConverter<Member>>();
Mapper.CreateMap<Member, string>().ConvertUsing<BaseToKeyConverter<Member>>();

public class KeyToBaseConverter<T> : ITypeConverter<string, T> where T : AceOfBase
{
    public RedisRepository Repository { get; set; }
    public T Convert(ResolutionContext context)
    {
        return Repository.GetByKey<T>(context.SourceValue.ToString());
    }
}
public class BaseToKeyConverter<T> : ITypeConverter<T, string> where T : AceOfBase
{
    public string Convert(ResolutionContext context)
    {
        var f = context.SourceValue as AceOfBase;
        return f.Key;
    }
}

唯一需要解决的组件是确保任何ListsSets我创建的任何密钥都获得相同的格式。

使用此模式,我将能够在字符串客户端旁边无缝使用强类型客户端,确保即使在没有强类型客户端的情况下拉取对象时,我也可以通过仅检查来确定 JSON blob 并将其安全地转换为正确的类型关键属性。

于 2013-10-24T13:38:54.253 回答