Я хочу иметь возможность украшать службы и конечные точки WCF следующим образом:
[CacheBehavior]
public class MyService
{ }
Когда вызывается операция, я хочу иметь возможность искать URL-адрес запроса как ключ кэша, и если найден кэшированный ответ, немедленно возвращать необработанный ответ, извлекая предварительно отформатированную строку JSON из моего кэша. Поступая так, я бы избегал вызова фактического метода конечной точки.
Когда операция не найдена в кеше, я хочу выполнить некоторую логику при возврате ответа и записать необработанный ответ (JSON) в свой кеш с тем же ключом кеша.
Я просмотрел примеры по адресу https://github.com/dotnet/samples/tree/main/framework/wcf и попробовал использовать ChannelMessageInterceptor, ChannelDispatcherBase, IDispatchMessageInspector и IOperationInvoker, но ни один из них, похоже, не поддерживает такое использование. случай. Если только я что-то не упускаю.
Я думаю, вы неправильно поняли вопрос. Дело не в том, что я не могу заставить его работать. Дело в том, что я не знаю, какой тип поведения или функция расширяемости WCF действительно можно использовать для этого варианта использования.





Я смог использовать 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.
Вы добавили <behaviorExtensions> <add name = "CacheBehavior" type = "Namespace.CacheBehaviorExtension, AssemblyName" /> </behaviorExtensions> в web.config?