Очередной совет из серии "хорошо за 5 минут" - логируем вызов метода вместе со списком и значениями входных параметров!
Пусть будет для примера старинный ASMX клиент:
public partial class LegacyClient : System.ServiceModel.ClientBase<Legacy>, Legacy
у которого большое количество методов, переплетенных в причудливые макаронины вместе с остальным кодом. Писать свою обертку долго и больно, а логировать вызовы надо. Будем делать на аспектах с помощью DI-контейнера! В данном примере - Ninject. Конкретный контейнер не так важен. Важно, поддерживает ли он "перехватчики" - interceptors. На том, что такое Dependency Injection и DI-контейнеры - останавливаться не буду, все уже жевано-пережевано до меня.Поехали, выделяем интерфейс с нужными методами (R# спешит на помощь):
public partial class LegacyClient : ILegacyClient {}
В конфиге контейнера указываем наш interceptor:Kernel.Bind(typeof(ILegacyClient))
.To<LegacyClient>()
.Intercept()
.With<LogRequestInterceptor>();
А вот и реализация interceptor'а: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
invocation.Proceed();
}
}
Дополнительно к нашему "перехватчику" необходимо реализовать сериализацию аргументов метода (я предпочитаю JSON).
Получение объекта с дополнительными аспектами ничем не отличается от обычного resolve'а с помощью DI:
ILegacyClient client = Kernel.GetService<ILegacyClient>();
client.AnyMethodCall(...);
Самое важное в этом примере - мы не меняем интерфейс класса LegacyClient, поэтому вызывающий методы данного класса код остается нетронутым, и измениться не может в принципе. Необходимо лишь изменить способ создания объекта, что зачастую является куда менее трудоемкой задачей, чем написание прокси-класса. На этом всё, побольше удачи и поменьше рутины!
Комментариев нет:
Отправить комментарий