Регистрация входа и выхода методов вместе с параметрами автоматически?

Есть ли способ добавить запись в журнал, чтобы входящие и выходящие методы автоматически каким-либо образом регистрировались вместе с параметрами для целей трассировки? Как бы я это сделал?

Я использую Log4Net.

Ответы на вопрос(7)

Декоратор Pattern может помочь

функции

избегая повторения кода и в том числеварианты аргументов:

private static void LogEnterExit(bool isEnter = true, params object[] args)
{
    StackTrace trace = new StackTrace(true);  // need `true` for getting file and line info
    if (trace.FrameCount > 2)
    {
        string ns = trace.GetFrame(2).GetMethod().DeclaringType.Namespace;
        string typeName = trace.GetFrame(2).GetMethod().DeclaringType.Name;
        string args_string = args.Length == 0 ? "" : "\narguments: [" + args.Aggregate((current, next) => string.Format("{0},{1};", current, next))+"]";
        Console.WriteLine("{0} {1}.{2}.{3}{4}", isEnter ? "Entering" : "Exiting", ns, typeName, trace.GetFrame(2).GetMethod().Name, args_string );
    }
}

static void LogEnter(params object[] args)
{
    LogEnterExit(true, args);
}

static void LogExit(params object[] args)
{
    LogEnterExit(false, args);
}
использование
static void DoSomething(string arg1)
{
    LogEnter(arg1);
    Console.WriteLine("Executing DoSomething");
    LogExit();
}
Выход

В консоли это будет вывод, еслиDoSomething были запущены сбла» какarg1

Entering Program.DoSomething
arguments: [blah]
Executing DoSomething
Exiting Program.DoSomething

каковы ваши реальные потребности, но здесьЭто вариант с низкой арендной платой. Это'не совсем "автоматический», но вы можете использовать StackTrace для очистки информации, которую выищет таким образом, что быне требует передачи аргументов - похоже на ckramer 'Предложение относительно перехвата:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;

namespace TracingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething();
        }

        static void DoSomething()
        {
            LogEnter();

            Console.WriteLine("Executing DoSomething");

            LogExit();
        }

        static void LogEnter()
        {
            StackTrace trace = new StackTrace();
            if (trace.FrameCount > 1)
            {
                string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
                string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
                Console.WriteLine("Entering {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
            }
        }

        static void LogExit()
        {
            StackTrace trace = new StackTrace();
            if (trace.FrameCount > 1)
            {
                string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
                string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
                Console.WriteLine("Exiting {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
            }
        }
    }
}

Вы можете объединить что-то вроде приведенного выше примера с наследованием, используя не виртуальный открытый член в базовом типе для обозначения метода действия, а затем вызвать виртуального члена для фактического выполнения работы:

public abstract class BaseType
{
    public void SomeFunction()
    {

        LogEnter();
        DoSomeFunction();
        LogExit();
    }

    public abstract void DoSomeFunction();
}

public class SubType : BaseType
{
    public override void DoSomeFunction()
    {
        // Implementation of SomeFunction logic here...
    }
}

Снова - тамне много "автоматический» об этом, но это будет работать на ограниченной основе, если вы неНе требуется инструментарий при каждом вызове метода.

Надеюсь это поможет.

 parliament17 окт. 2014 г., 04:44
Этот код хорошо сочетается с этим кодом для захвата значений параметровstackoverflow.com/a/6928253/1267778 , Так что у меня есть что-то вроде logService.LogEnter (arg1, arg2, arg3). Качественный товар

Есть несколько способов сделать это, хотя все они имеют тенденцию быть несколько агрессивными. Можно было бы извлечь все ваши объекты из ContextBoundObject.Вот пример использования такого подхода Другой подход заключается в использовании одной из существующих библиотек АОП для достижения этой цели. Что-то вроде DynamicProxy отПроект Замка лежит в основе многих из них. Вот несколько ссылок:Spring.Net PostSharp Сесил

Есть, вероятно, несколько других, и я знаю,Замок Виндзор, а такжеNinject оба предоставляют возможности АОП поверх функциональности IoC.

Как только AOP будет установлен, вы просто напишите класс-перехватчик, который будет записывать информацию о методах, вызываемых в log4net.

Я бы на самом деле нене удивлюсь, если одна из платформ AOP предоставит вам такую функциональность из коробки.

CInject на CodePlex, у которого есть LogInjector, чтобы отметить вход и выход вызова метода.

Или вы можете выполнить шаги, упомянутые в этой статье наПерехват вызовов методов с использованием IL и создайте свой собственный перехватчик, используя классы Reflection.Emit в C #.

PostSharp, Пример с сайта говорит о настройке трассировщика для входа / выхода из метода, который очень похож на то, что вы хотите.

Как перехватить вызов метода в C #? PostSharp - ткачество иль - мысли

Также ищите ТАК для 'АОП» или же 'Аспектно-ориентированное программирование » и PostSharp ... вы получите интересные результаты.

Ваш ответ на вопрос