我现在创建了一个提供密钥空间分区IDatabase
的包装器。
包装器是通过使用扩展方法创建的IDatabase
ConnectionMultiplexer multiplexer = ConnectionMultiplexer.Connect("localhost");
IDatabase fullDatabase = multiplexer.GetDatabase();
IDatabase partitioned = fullDatabase.GetKeyspacePartition("my-partition");
分区包装器中的几乎所有方法都具有相同的结构:
public bool SetAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
{
return this.Inner.SetAdd(this.ToInner(key), value, flags);
}
他们只是将调用转发到内部数据库,并RedisKey
在传递它们之前将键空间前缀添加到任何参数。
CreateBatch
and方法只是为这些CreateTransaction
接口创建包装器,但使用相同的基本包装器类(因为大多数包装方法由 定义IDatabaseAsync
)。
不支持KeyRandomAsync
and方法。KeyRandom
调用将抛出一个NotSupportedException
. 这不是我关心的问题,引用@Marc Gravell:
我想不出任何明智的方法来实现这一点,但我怀疑 NotSupportedException("RANDOMKEY is not supported when a key-prefix is specified") 是完全合理的(无论如何这不是常用的命令)
我还没有实现ScriptEvaluate
,ScriptEvaluateAsync
因为我不清楚我应该如何处理RedisResult
返回值。这些方法的输入参数接受RedisKey
应该加前缀的参数,但是脚本本身可以返回键,在这种情况下,我认为(最)不加前缀是有意义的。暂时,这些方法会抛出一个NotImplementedException
......
排序方法(Sort
、SortAsync
和)对SortAndStore
和参数有SortAndStoreAsync
特殊处理。除非它们具有特殊值之一: for和for ,否则这些前缀正常。by
get
nosort
by
#
get
最后,为了允许添加前缀,ITransaction.AddCondition
我不得不使用一点反射:
internal static class ConditionHelper
{
public static Condition Rewrite(this Condition outer, Func<RedisKey, RedisKey> rewriteFunc)
{
ThrowIf.ArgNull(outer, "outer");
ThrowIf.ArgNull(rewriteFunc, "rewriteFunc");
Type conditionType = outer.GetType();
object inner = FormatterServices.GetUninitializedObject(conditionType);
foreach (FieldInfo field in conditionType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
if (field.FieldType == typeof(RedisKey))
{
field.SetValue(inner, rewriteFunc((RedisKey)field.GetValue(outer)));
}
else
{
field.SetValue(inner, field.GetValue(outer));
}
}
return (Condition)inner;
}
}
包装器使用此帮助器,如下所示:
internal Condition ToInner(Condition outer)
{
if (outer == null)
{
return outer;
}
else
{
return outer.Rewrite(this.ToInner);
}
}
ToInner
对于包含的不同类型的参数,还有其他几种方法,RedisKey
但它们都或多或少地最终调用:
internal RedisKey ToInner(RedisKey outer)
{
return this.Prefix + outer;
}
我现在为此创建了一个拉取请求:
https://github.com/StackExchange/StackExchange.Redis/pull/92
现在调用了扩展方法WithKeyPrefix
,并且不再需要用于重写条件的反射黑客,因为新代码可以访问Condition
类的内部。