tipos - try catch c# messagebox
Registro genérico de parámetros de funciones en el manejo de excepciones (7)
Cuando hice esto, acabo de crear un diccionario genérico para el registro.
Tengo esta clase LogArgs. Y al iniciar sesión en una clase base a la que llamo cuando tengo una excepción.
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>();
}
}
Luego, al comienzo de cada método que hago
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);
Cuando tengo un error, lo registro de esta manera.
base.Logger.LogError(args, ex);
Mucho de mi código C # sigue este patrón:
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));
}
}
¿Hay alguna manera en .NET de obtener una lista de clave / valor de los parámetros para una función, de modo que pueda llamar a otra función para construir mi cadena de registro de errores? O ¿Tiene una forma más genérica / mejor de hacer esto?
No, no hay una manera de hacer esto.
La práctica habitual es no detectar excepciones a menos que pueda manejarlas.
Es decir, normalmente solo detectaría excepciones y las registraría en un manejador de excepciones de nivel superior. A continuación, obtendrá un seguimiento de pila, pero por supuesto no obtendrá detalles de todos los parámetros de todas las llamadas a métodos en la pila.
Obviamente, cuando se depura, se necesitan tantos detalles como sea posible. Otras formas de lograr esto son:
Use las sentencias Debug.Assert liberalmente para probar las suposiciones que está haciendo.
Instrumente su aplicación con el registro que se puede activar selectivamente. Uso Log4Net, pero también hay otras alternativas, incluida la utilización de la clase System.Diagnostics.Trace.
En cualquier caso, si detecta excepciones solo para registrarlas (lo haría en un límite de nivel en una aplicación de n niveles, para que las excepciones se registren en el servidor), siempre debe volver a lanzarlas:
try
{
...
}
catch(Exception ex)
{
log(ex);
throw;
}
Puede usar Reflection y la convención de que debe pasar los parámetros al LogError con el orden correcto:
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));
}
Puede usar un estilo similar de construcción del mensaje, pero agregue la palabra clave params en su método LogError para manejar los argumentos. Por ejemplo:
public void LogError(string message, params object[] parameters)
{
if (parameters.Length > 0)
LogError(string.Format(message, parameters));
else
LogError(message);
}
Hay escenarios de algunos parámetros o gran cantidad de parámetros ...
Pocos parámetros, sin mucho preámbulo, mejor escribirlos como parte del mensaje de registro / excepción.
En grandes parámetros, una aplicación de múltiples capas usaría ENTITIES (como customer, CustomerOrder ...) para transferir datos entre capas. Estas entidades deberían implementar reemplazar los métodos ToString () de la clase Object, allí por,
Logmessage ("método iniciado" + paramObj.ToString ()) daría la lista de datos en el objeto .. ¿Alguna opinión? :)
Gracias
Puede utilizar la programación orientada a aspectos con PostSharp (eche un vistazo a http://www.postsharp.org y el tutorial en http://www.codeproject.com/KB/cs/ps-custom-attributes-1.aspx ) Básicamente puedes hacer algo como esto:
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
}
Quizás no sea exactamente lo que quiere, pero estoy seguro de que se puede adaptar a sus necesidades.
Esta es una publicación poco fechada, pero en caso de que alguien se encuentre con esto como lo hice, resolví este problema usando PostSharp .
Aunque no es prácticamente gratis. La licencia Express (descargable a través de NuGet en VS) le permite decorar su método con el atributo [Log]
y luego elegir su mecanismo ya configurado para el registro, como log4net nLog, etc. Ahora comenzará a ver las entradas de nivel de Debug en su registro. .
Con licencia expresa, solo pude decorar un máximo de 50 métodos en mi proyecto. Si se adapta a tus necesidades, ¡ya estás listo!