Ведение журнала как сквозная проблема в WCF
Я хотел бы войти в файл каждый раз, когда мой веб-сервис вызывается, записывая имя вызываемого метода, а также данные вызова.
Для записи в этот файл я использую Nlog, но я не хотел бы делать вызов регистрации в каждой из моих служебных операций. Я бы предпочел как-то автоматизировать этот вызов регистрации как сквозную задачу.
Является ли это возможным?
3 ответа
Вы можете использовать DI-контейнер, поддерживающий перехватчики, для регистрации любого вызова метода WCF с входными значениями. Вот пример для Ninject
и старый странный сервис ASMX (для WCF идея одна и та же):
Давайте рассмотрим следующий класс клиента:
public partial class LegacyClient : System.ServiceModel.ClientBase<Legacy>, Legacy
Поскольку этот класс является частичным, мы можем легко добавить к классу интерфейс ILegacyClient
содержащие методы, которые мы хотим вызвать. ReSharper извлеките интерфейс за секунду. Поместите частичное объявление класса в отдельный файл:
public partial class LegacyClient : ILegacyClient {}
В DI config добавьте перехватчик:
Kernel.Bind(typeof(ILegacyClient))
.To<LegacyClient>()
.InRequestScope() //carefully choose a scope
.Intercept()
.With<LogRequestInterceptor>();
LogRequestInterceptor
самая интересная часть:
using Ninject;
using Ninject.Extensions.Interception;
public class LogRequestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
MethodInfo method = invocation.Request.Method;
var parameters = method.GetParameters();
var builder = new StringBuilder();
for (int index = 0; index < parameters.Length; index++)
{
object argument = invocation.Request.Arguments[index];
ParameterInfo parameterInfo = parameters[index];
if (!parameterInfo.IsOut)
{
//use any serialization you like
string text = $"{parameterInfo.Name} = {argument.ToJson()}, ";
builder.Append(text);
}
}
string joinedParameters = builder.ToString();
YourLogging(method.Name, joinedParameters);
//LegacyClient method call, don't forget this line
invocation.Proceed();
}
}
Последняя часть, чтобы заставить вещи работать. Создайте прокси-объект через DI и используйте его:
ILegacyClient client = Kernel.GetService<ILegacyClient>();
client.AnyMethodCall(...);
Прямое создание - только пример, конечно, вы можете использовать вместо этого конструктор или внедрение свойства и при необходимости заменить клиентский интерфейс на фабричный.
Надеюсь, поможет!
Вы можете попробовать использовать либо Аспектно-ориентированное программирование (AOP), используя Windsor Castle, PostSharp, либо другие сторонние библиотеки, предлагающие AOP. Также вы можете использовать перехватчики из этих библиотек.
Расширение WCF может быть другим местом для ведения такого рода регистрации.
Использование трассировки WCF. Вы можете просматривать сервисные вызовы, сведения об уровне сообщений и т. Д., Включив трассировку WCF по Конфигурации.
Ответ Abhinav Galodha правильный, но слишком общий, поэтому я бы просто добавил ссылку на то, как реализовать №2. Я думаю, это именно то, что автор хочет задать.
В двух словах, вы можете реализовать свой собственный инспектор параметров (IParameterInspector
) и внедрить его с помощью служебного поведения (IServiceBehavior
). Здесь вы можете найти полный пример, как это сделать для регистрации.