Генерирование регистрации параметров функции при обработке исключений
Многое из моего кода на С# следует этому шаблону:
void foo(string param1, string param2, string param3)
{
try
{
// do something...
}
catch(Exception ex)
{
LogError(String.Format("Error in foo(param1={0}, param2={1}, param3={2}), exception={3}", param1, param2, param3, ex.Message));
}
}
Есть ли способ в .NET, чтобы получить список параметров Key/Value для функции, чтобы я мог вызвать другую функцию для построения строки регистрации ошибок?
ИЛИ
У вас есть более общий/лучший способ сделать это?
Ответы
Ответ 1
Вы можете использовать Reflection и соглашение, что вы должны передать параметры LogError в правильном порядке:
private static void MyMethod(string s, int x, int y)
{
try
{
throw new NotImplementedException();
}
catch (Exception ex)
{
LogError(MethodBase.GetCurrentMethod(), ex, s, x, y);
}
}
private static void LogError(MethodBase method, Exception ex, params object[] values)
{
ParameterInfo[] parms = method.GetParameters();
object[] namevalues = new object[2 * parms.Length];
string msg = "Error in " + method.Name + "(";
for (int i = 0, j = 0; i < parms.Length; i++, j += 2)
{
msg += "{" + j + "}={" + (j + 1) + "}, ";
namevalues[j] = parms[i].Name;
if (i < values.Length) namevalues[j + 1] = values[i];
}
msg += "exception=" + ex.Message + ")";
Console.WriteLine(string.Format(msg, namevalues));
}
Ответ 2
Вы можете использовать аспектно-ориентированное программирование с помощью PostSharp (посмотрите http://www.postsharp.org, а учебник на http://www.codeproject.com/KB/cs/ps-custom-attributes-1.aspx). В основном вы можете сделать что-то вроде этого:
public class LogExceptionAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionEventArgs eventArgs)
{
log.error("Exception occurred in method {0}", eventArgs);
}
}
[LoggingOnExceptionAspect]
public foo(int number, string word, Person customer)
{
// ... something here throws an exception
}
Возможно, не совсем то, что вы хотите, но я уверен, что он может быть адаптирован в соответствии с вашими потребностями.
Ответ 3
Нет никакого способа сделать это.
Обычная практика заключается в том, чтобы не перехватывать исключения, если вы не можете их обработать.
т.е. вы обычно будете ловить исключения и записывать их в обработчик исключений верхнего уровня. Затем вы получите трассировку стека, но, конечно же, не получите подробную информацию обо всех параметрах всех вызовов методов в стеке.
Очевидно, что при отладке вы хотите как можно больше деталей. Другие способы достижения этого:
-
Используйте операторы Debug.Assert, чтобы анализировать допущения, которые вы делаете.
-
Инструмент приложения с протоколированием, который можно активировать выборочно. Я использую Log4Net, но есть и другие альтернативы, включая использование класса System.Diagnostics.Trace.
В любом случае, если вы перехватываете исключения только для их регистрации (я бы сделал это на границе уровня в приложении n-уровня, чтобы исключения регистрировались на сервере), тогда вы всегда должны их сверять:
try
{
...
}
catch(Exception ex)
{
log(ex);
throw;
}
Ответ 4
Когда я это сделал, я просто создал общий словарь для ведения журнала.
У меня есть этот класс LogArgs. И вход в базовый класс, который я вызываю, когда у меня есть исключение.
public class LogArgs
{
public string MethodName { get; set; }
public string ClassName { get; set; }
public Dictionary<string, object> Paramters { get; set; }
public LogArgs()
{
this.Paramters = new Dictionary<string, object>();
}
}
Тогда в начале каждого метода я делаю
LogArgs args = new LogArgs { ClassName = "ClassName", MethodName = "MethodName" };
args.Paramters.Add("Param1", param1);
args.Paramters.Add("Param2", param2);
args.Paramters.Add("Param3", param3);
base.Logger.MethodStartLog(args);
Когда у меня есть ошибка, я регистрирую ее таким образом.
base.Logger.LogError(args, ex);
Ответ 5
Вы можете использовать похожий стиль построения сообщения, но добавьте ключевое слово params в свой метод LogError для обработки аргументов. Например:
public void LogError(string message, params object[] parameters)
{
if (parameters.Length > 0)
LogError(string.Format(message, parameters));
else
LogError(message);
}
Ответ 6
Это небольшая датировка, но на всякий случай кто-то сталкивается с этим, как и я, - я решил эту проблему, используя PostSharp.
Это не практически бесплатно, хотя. Лицензия Express (загружаемая через NuGet в VS) позволяет вам украсить ваш метод атрибутом [Log]
, а затем выбрать уже настроенный механизм ведения журнала, например log4net nLog и т.д. Теперь вы начнете видеть записи уровня отладки в параметрах вашего журнала.
С помощью экспресс-лицензии я мог только украсить максимум 50 методов в моем проекте. Если это соответствует вашим потребностям, вам хорошо идти!
Ответ 7
Существуют сценарии нескольких параметров или Большое количество параметров...
-
Несколько параметров без особого шума лучше записывать их как часть сообщения о регистрации/исключении.
-
В больших параметрах многоуровневое приложение будет использовать ENTITIES (например, Customer, CustomerOrder...) для передачи данных между слоями. Эти организации должны внедрять
переопределить методы ToString() класса Object, там,
Logmessage ( "метод запущен" + paramObj.ToString()) предоставит список данных в объекте.
Любые мнения?:)
спасибо