C# 中的异常
Exceptions in C#
我正在尝试编写文档完善的代码,如果处理了某些异常,该代码也将易于调试。因此,我的方法会抛出异常,它们会收集在我可以浏览的日志中。但是,在抛出新的异常时,写复杂的消息确实不太合适。我想编写一个简单的实用程序来收集:
- 当前姓名class
- 当前方法的名称
- 方法的参数
这可以通过一些简单的方法实现吗?另外,是否有更好的方法来制作此类异常日志?也许这个问题正在以不同的方式解决,所以请与我分享您的经验:)
异常已在其 StackTrace
中包含此信息。
要访问它,只需使用 public getter:
catch(Exception ex)
{
string trace = ex.StackTrace;
}
如果你想记录它,大多数记录器都有一个重载,它需要一个异常。将记录消息和堆栈跟踪。
例如,对于log4net,你可以使用方法void Error(object message, Exception t);
:
catch(Exception ex)
{
logger.Error("More details", ex);
}
您好获取带有签名的方法的名称修复是
//get the stack trace
StackTrace stackTrace = new StackTrace();
//the count may vary
MethodBase CallingMethod = stackTrace.GetFrame(2).GetMethod();
//Method called by
string _signatures = MethodInfoExtensions.GetSignature((MethodInfo)CallingMethod));
和 class
public static class MethodInfoExtensions
{
/// <summary>
/// Return the method signature as a string.
/// </summary>
/// <param name="method">The Method</param>
/// <param name="callable">Return as an callable string(public void a(string b) would return a(b))</param>
/// <returns>Method signature</returns>
public static string GetSignature(this MethodInfo method, bool callable = false)
{
var firstParam = true;
var sigBuilder = new StringBuilder();
if (callable == false)
{
if (method.IsPublic)
sigBuilder.Append("public ");
else if (method.IsPrivate)
sigBuilder.Append("private ");
else if (method.IsAssembly)
sigBuilder.Append("internal ");
if (method.IsFamily)
sigBuilder.Append("protected ");
if (method.IsStatic)
sigBuilder.Append("static ");
sigBuilder.Append(TypeName(method.ReturnType));
sigBuilder.Append(' ');
}
sigBuilder.Append(method.Name);
// Add method generics
if (method.IsGenericMethod)
{
sigBuilder.Append("<");
foreach (var g in method.GetGenericArguments())
{
if (firstParam)
firstParam = false;
else
sigBuilder.Append(", ");
sigBuilder.Append(TypeName(g));
}
sigBuilder.Append(">");
}
sigBuilder.Append("(");
firstParam = true;
var secondParam = false;
foreach (var param in method.GetParameters())
{
if (firstParam)
{
firstParam = false;
if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false))
{
if (callable)
{
secondParam = true;
continue;
}
sigBuilder.Append("this ");
}
}
else if (secondParam == true)
secondParam = false;
else
sigBuilder.Append(", ");
if (param.ParameterType.IsByRef)
sigBuilder.Append("ref ");
else if (param.IsOut)
sigBuilder.Append("out ");
if (!callable)
{
sigBuilder.Append(TypeName(param.ParameterType));
sigBuilder.Append(' ');
}
sigBuilder.Append(param.Name);
}
sigBuilder.Append(")");
return sigBuilder.ToString();
}
/// <summary>
/// Get full type name with full namespace names
/// </summary>
/// <param name="type">Type. May be generic or nullable</param>
/// <returns>Full type name, fully qualified namespaces</returns>
public static string TypeName(Type type)
{
var nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null)
return nullableType.Name + "?";
if (!type.IsGenericType)
switch (type.Name)
{
case "String": return "string";
case "Int32": return "int";
case "Decimal": return "decimal";
case "Object": return "object";
case "Void": return "void";
default:
{
return string.IsNullOrWhiteSpace(type.FullName) ? type.Name : type.FullName;
}
}
var sb = new StringBuilder(type.Name.Substring(0,
type.Name.IndexOf('`'))
);
sb.Append('<');
var first = true;
foreach (var t in type.GetGenericArguments())
{
if (!first)
sb.Append(',');
sb.Append(TypeName(t));
first = false;
}
sb.Append('>');
return sb.ToString();
}
}
我正在尝试编写文档完善的代码,如果处理了某些异常,该代码也将易于调试。因此,我的方法会抛出异常,它们会收集在我可以浏览的日志中。但是,在抛出新的异常时,写复杂的消息确实不太合适。我想编写一个简单的实用程序来收集:
- 当前姓名class
- 当前方法的名称
- 方法的参数
这可以通过一些简单的方法实现吗?另外,是否有更好的方法来制作此类异常日志?也许这个问题正在以不同的方式解决,所以请与我分享您的经验:)
异常已在其 StackTrace
中包含此信息。
要访问它,只需使用 public getter:
catch(Exception ex)
{
string trace = ex.StackTrace;
}
如果你想记录它,大多数记录器都有一个重载,它需要一个异常。将记录消息和堆栈跟踪。
例如,对于log4net,你可以使用方法void Error(object message, Exception t);
:
catch(Exception ex)
{
logger.Error("More details", ex);
}
您好获取带有签名的方法的名称修复是
//get the stack trace
StackTrace stackTrace = new StackTrace();
//the count may vary
MethodBase CallingMethod = stackTrace.GetFrame(2).GetMethod();
//Method called by
string _signatures = MethodInfoExtensions.GetSignature((MethodInfo)CallingMethod));
和 class
public static class MethodInfoExtensions
{
/// <summary>
/// Return the method signature as a string.
/// </summary>
/// <param name="method">The Method</param>
/// <param name="callable">Return as an callable string(public void a(string b) would return a(b))</param>
/// <returns>Method signature</returns>
public static string GetSignature(this MethodInfo method, bool callable = false)
{
var firstParam = true;
var sigBuilder = new StringBuilder();
if (callable == false)
{
if (method.IsPublic)
sigBuilder.Append("public ");
else if (method.IsPrivate)
sigBuilder.Append("private ");
else if (method.IsAssembly)
sigBuilder.Append("internal ");
if (method.IsFamily)
sigBuilder.Append("protected ");
if (method.IsStatic)
sigBuilder.Append("static ");
sigBuilder.Append(TypeName(method.ReturnType));
sigBuilder.Append(' ');
}
sigBuilder.Append(method.Name);
// Add method generics
if (method.IsGenericMethod)
{
sigBuilder.Append("<");
foreach (var g in method.GetGenericArguments())
{
if (firstParam)
firstParam = false;
else
sigBuilder.Append(", ");
sigBuilder.Append(TypeName(g));
}
sigBuilder.Append(">");
}
sigBuilder.Append("(");
firstParam = true;
var secondParam = false;
foreach (var param in method.GetParameters())
{
if (firstParam)
{
firstParam = false;
if (method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false))
{
if (callable)
{
secondParam = true;
continue;
}
sigBuilder.Append("this ");
}
}
else if (secondParam == true)
secondParam = false;
else
sigBuilder.Append(", ");
if (param.ParameterType.IsByRef)
sigBuilder.Append("ref ");
else if (param.IsOut)
sigBuilder.Append("out ");
if (!callable)
{
sigBuilder.Append(TypeName(param.ParameterType));
sigBuilder.Append(' ');
}
sigBuilder.Append(param.Name);
}
sigBuilder.Append(")");
return sigBuilder.ToString();
}
/// <summary>
/// Get full type name with full namespace names
/// </summary>
/// <param name="type">Type. May be generic or nullable</param>
/// <returns>Full type name, fully qualified namespaces</returns>
public static string TypeName(Type type)
{
var nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null)
return nullableType.Name + "?";
if (!type.IsGenericType)
switch (type.Name)
{
case "String": return "string";
case "Int32": return "int";
case "Decimal": return "decimal";
case "Object": return "object";
case "Void": return "void";
default:
{
return string.IsNullOrWhiteSpace(type.FullName) ? type.Name : type.FullName;
}
}
var sb = new StringBuilder(type.Name.Substring(0,
type.Name.IndexOf('`'))
);
sb.Append('<');
var first = true;
foreach (var t in type.GetGenericArguments())
{
if (!first)
sb.Append(',');
sb.Append(TypeName(t));
first = false;
}
sb.Append('>');
return sb.ToString();
}
}