Существует ли способ добраться, массив аргументов передал методу?

''.join('_'+c.lower() if c.isupper() else c for c in "DeathToCamelCase").strip('_')
re.sub("(.)([A-Z])", r'\1_\2', 'DeathToCamelCase').lower()
26
задан David Henderson 20 July 2010 в 10:53
поделиться

8 ответов

Вот что я придумал в качестве решения:

PostSharp или другое решение АОП было нецелесообразно в этой ситуации, поэтому, к сожалению, мне пришлось отказаться от этой идеи.

Похоже, что хотя имена и типы параметров можно задавать с помощью отражения, единственный способ получить доступ к значениям времени выполнения - это подключить отладчик.

См. Здесь для получения дополнительной информации:

StackOverflow

microsoft.public.dotnet.framework

Так что это все еще оставило меня с проблемой ~ 50 методов, которые требовали добавления этого журнала вручную.

Отражение, чтобы спасти ...

public String GetMethodParameterArray()
    {
        var output = new StringBuilder();
        output.AppendLine();

        Type t = typeof(API);
        foreach (var mi in t.GetMethods())
        {
                var argsLine = new StringBuilder();
                bool isFirst = true;
                argsLine.Append("object[] args = {");
                var args = mi.GetParameters();

                foreach (var pi in args)
                {
                    if (isFirst)
                    {
                        isFirst = false;
                    }
                    else
                    {
                        argsLine.Append(", ");
                    }
                    argsLine.AppendFormat("{0}", pi.Name);
                }
                argsLine.AppendLine("};"); //close object[] initialiser

                output.AppendLine(argsLine.ToString());
                output.AppendFormat("Log(\"{0}\",args);", mi.Name);
                output.AppendLine();
                output.AppendLine();
            }
        return output.ToString();
    }

Этот фрагмент кода перебирает методы класса и выводит массив object [], инициализированный аргументами, переданными в метод, и вызовом журнала, содержащим аргументы и имя метода.

Пример вывода:

object[] args = {username, password, name, startDate, endDate, cost};
Log("GetAwesomeData",args);

Затем этот блок можно вставить в начало метода для достижения необходимого эффекта.

Это больше ручной ввод, чем мне бы хотелось, но он намного лучше, чем ввод параметров вручную, и гораздо менее подвержен ошибкам.

0
ответ дан 28 November 2019 в 17:25
поделиться

Я не уверен, что API для доступа к стеку вызовов предоставляет средства для получения списка аргументов.

Однако существуют способы внедрить IL для перехвата вызовов методов и выполнения пользовательского кода.

Библиотека, которую я часто использую, - PostSharp , автор Gael Fraiteur, она включает приложение, которое запускает postbuild и внедряет IL в ваши выходные сборки в зависимости от аспектов, которые вы используете. Существуют атрибуты, с помощью которых вы можете украшать сборки, типы или отдельные методы. Например:

[Serializable]
public sealed class LoggingAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs eventArgs)
    {
        Console.WriteLine("Entering {0} {1} {2}",
                          eventArgs.Method.ReflectedType.Name,
                          eventArgs.Method,
                          string.Join(", ", eventArgs.Arguments.ToArray()));

        eventArgs.MethodExecutionTag = DateTime.Now.Ticks;
    }

    public override void OnExit(MethodExecutionArgs eventArgs)
    {
        long elapsedTicks = DateTime.Now.Ticks - (long) eventArgs.MethodExecutionTag;
        TimeSpan ts = TimeSpan.FromTicks(elapsedTicks);

        Console.WriteLine("Leaving {0} {1} after {2}ms",
                          eventArgs.Method.ReflectedType.Name,
                          eventArgs.Method,
                          ts.TotalMilliseconds);
    }
}

После этого вы можете просто украсить метод, который вы хотите с этим атрибутом:

[Logging]
public void SomeMethod(String p1, String p2, int p3) 
{
   //..
}
5
ответ дан Anirudha Gupta 28 November 2019 в 17:25
поделиться

Хорошо params помогают с вызовом журнала, но не помогают существующим сигнатурам методов. Ведение журнала с использованием AOP Framework может быть более продуктивным подходом?

1
ответ дан si618 28 November 2019 в 17:25
поделиться

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

0
ответ дан Johann Strydom 28 November 2019 в 17:25
поделиться

Если вы используете Postsharp, вы можете просто добавить атрибут к методу, который вы хотите логировать. Внутри этого атрибута вы можете написать код протоколирования, а также предоставить необходимые аргументы. Это известно как сквозные проблемы и AOP (Aspect oriented programming)

.
7
ответ дан 28 November 2019 в 17:25
поделиться

может не работать в некоторых сценариях, но должно помочь вам начать :)

class Program
{
    static void Main(string[] args)
    {
        M1("test");
        M2("test", "test2");
        M3("test", "test2", 1);

        Console.ReadKey();
    }

    static void M1(string p1)
    {
        Log(MethodBase.GetCurrentMethod());
    }

    static void M2(string p1, string p2)
    {
        Log(MethodBase.GetCurrentMethod());
    }

    static void M3(string p1, string p2, int p3)
    {
        Log(MethodBase.GetCurrentMethod());
    }

    static void Log(MethodBase method)
    {
        Console.WriteLine("Method: {0}", method.Name);
        foreach (ParameterInfo param in method.GetParameters())
        {
            Console.WriteLine("ParameterName: {0}, ParameterType: {1}", param.Name, param.ParameterType.Name);
        }
    }
}
0
ответ дан 28 November 2019 в 17:25
поделиться

Что ж, если вы просто хотите передать значения, вы можете обмануть и определить массив объектов:

public static void LogParameters(params object[] vals)
{

}

Это приведет к блокировке типов значений, а также не даст вам никаких имен параметров, однако .

Допустим, у меня есть метод:

 public void SomeMethod(String p1, String p2, int p3) 
 { 

 #if DEBUG 
    LogParamaters(p1, p2, p3); 
 #endif 

     // Do Normal stuff in the method 
 } 

Обновление: к сожалению, отражение не сделает все автоматически за вас. Вам нужно будет указать значения, но вы можете использовать отражение, чтобы указать имена / типы параметров:

Как вы можете получить имена параметров метода?

Таким образом, подпись метода изменится на что-то вроде:

public static void LogParameters(string[] methodNames, params object[] vals)
{ }

Затем вы можете принудительно / предположить, что каждый индекс в каждой коллекции совпадает, так что methodNames [0] имеет значение vals [0] .

2
ответ дан 28 November 2019 в 17:25
поделиться

Пока вы знаете, какие типы ожидать, вы можете регистрировать их в базе данных SQL. Напишите метод, который выполняет проверку типа, а затем заполняет соответствующий столбец БД значением параметра (аргумента). Если у вас есть пользовательский тип, вы можете использовать имя типа и сохранить его как строку в отдельном специальном столбце.

-Edit

Также, используя метод расширения MethodBase.Name, вы можете связать ваши параметры с методом, который принял их в качестве аргументов, как упоминалось в другом сообщении ниже. Это было бы удобным способом отслеживания всех использованных методов, с какими аргументами и какого типа.

Это хотя бы смутно хорошая идея? :)

.
0
ответ дан 28 November 2019 в 17:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: