我希望能够像这样装饰 WCF 服务和端点:
[CacheBehavior]
public class MyService
{ }
调用操作时,我希望能够将请求 URL 作为缓存键进行查找,如果找到缓存的响应,则通过从缓存中获取预格式化的 JSON 字符串来立即返回原始响应。通过这样做,我可以避免调用实际的端点方法。
当在缓存中找不到操作时,我想在返回响应时执行一些逻辑,并使用相同的缓存键将原始响应(JSON)写入我的缓存。
我查看了https://github.com/dotnet/samples/tree/main/framework/wcf的示例,并尝试使用 ChannelMessageInterceptor、ChannelDispatcherBase、IDispatchMessageInspector 和 IOperationInvoker,但这些似乎都不支持这种使用案件。除非我错过了什么。
我能够在这个用例中使用
IOperationInvoker
,唯一需要注意的是它无法缓存预序列化响应,因为它期望返回一个对象。因此,在缓存或从缓存中获取时,我必须序列化/反序列化响应。
带有内存缓存的模拟代码:
public class CacheOperationInvoker : IOperationInvoker
{
private static readonly Dictionary<string, object> _cache = new Dictionary<string, object>();
private readonly IOperationInvoker _invoker;
public bool IsSynchronous => true;
public CacheOperationInvoker(IOperationInvoker baseInvoker)
{
this._invoker = baseInvoker;
}
public object[] AllocateInputs()
{
return _invoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var operationContext = WebOperationContext.Current;
var cacheKey = operationContext?.IncomingRequest.UriTemplateMatch.RequestUri.OriginalString;
if (_cache.ContainsKey(cacheKey))
{
outputs = new object[] { };
return _cache[cacheKey];
}
var result = _invoker.Invoke(instance, inputs, out outputs);
_cache[cacheKey] = result;
return result;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
throw new Exception("The operation invoker is not asynchronous.");
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
throw new Exception("The operation invoker is not asynchronous.");
}
}
否则,我缺少的部分是需要使用
OperationContext.Current
或 WebOperationContext.Current
从传入请求访问其他上下文,因为它没有直接提供给 IOperationInvoker
。