在挖掘了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 一样正常使用关系。
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; }
}
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;
}
}
唯一需要解决的组件是确保任何Lists
或Sets
我创建的任何密钥都获得相同的格式。
使用此模式,我将能够在字符串客户端旁边无缝使用强类型客户端,确保即使在没有强类型客户端的情况下拉取对象时,我也可以通过仅检查来确定 JSON blob 并将其安全地转换为正确的类型关键属性。