您能否设置任何信息并将其传递给*标准自动*异常处理流程以包含在异常中?
Can you set and pass any information to the *standard automatic* exception handling process to be included in the exception?
在任何方法中,您是否可以设置在异常处理过程中自动拾取的内容?
以下将向调用程序冒泡 ErrorMessage 和原始异常。
void Main()
{
string ErrorMessage = "FooBar";
try
{
throw new Exception();
}
catch (Exception ex)
{
throw new Exception(ErrorMessage, ex);
}
}
有没有办法在没有 Try/Catch/Re-Throw 的情况下复制它?
重述问题:
有没有什么办法让它(以任何方式)自动获取我指定的异常?
void Main()
{
string ErrorMessage = "FooBar";
throw new Exception();
}
所以我了解了抛出新异常的概念并提供了更多信息。我有兴趣找到一种方法,当发生异常时,它会自动获取自定义信息(“FooBar”),并且 returns Try/Catch/Re-Throw 完成的事情,没有 Try/Catch 和重新投掷。
** 已编辑 **
当无需重新抛出而自然生成的异常到达 errorHandler 时,我希望能够检索我的 ErrorMessage(比如 ex.data?),其中包含“FooBar”。
void ErrorHandler(Exception ex)
{
Log(ex.Data); // ex.Data is set to "FooBar";
}
“例外系统如何知道您希望在例外中包含哪些自定义数据?”
这是我提问的基础。我能用它知道什么? :P
另一个有助于表达我正在寻找的想法:
public class CustomException : Exception
{
public CustomException() { }
public CustomException(string message) : base(message) { }
public CustomException(string message, Exception inner) : base(message, inner) { }
public string ErrorMessage { get; set;}
}
void Main()
{
CustomException cEx = new CustomException {ErrorMessage = "FooBar"};
throw new Exception(); // This would be any arbitrary error, not one I'm throwing...
}
然后在 ExceptionHandler 事件中,可能会覆盖新异常的创建,如:
if (cEx != null)
{
// Use cEx in place of new Exception() as the error to fill to send
}
else
{
// Use new Exception() as the error to fill to send
}
“在我看来,您可能将日志记录与异常管理混淆了 - 看起来您想要自动收集的信息通常是您的日志记录策略的一部分。”
好的,假设你是对的。
所以,我不想每次进来都记录,我只想记录随机错误发生时的信息。假设我想知道任何传入参数在传入时以及在它们有机会更改之前的值。
错误的StackTrace会告诉我Method Name和Parameters的名称以及Parameters的TYPES。一切顺利。
但我找不到获取传入的值的方法,因为第一,我无法找到它们,第二,它们可能在发送后发生了变化。
显然我可以确保我不会更改输入的内容,但如果我无论如何都无法获取这些值,那也无济于事。
也许解决这个问题就能解决我关于如何处理错误的问题。
所以现在另一个问题是“如何仅在出现异常时记录任何传入参数的值?”
我的问题可能太具体了(我在这里问的问题不多,我还在学习这里的交互。)也许我应该问:
如果我想要一条由以下内容组成的错误消息:
"Error in myAssembly.GetStudentName(27)"
其中 27 是一个整数(可能是 StudentID),如果没有 Try/Catch/Rethrow 我怎么能做到呢?
我可以创建一串
"Error in myAssembly.GetStudentName(27)"
进入每个方法。我不能做的是在没有 Try/Catch 的任何异常情况下获取该字符串并对其执行任何操作。
如果我对你的理解正确,你希望避免在任何地方编写错误处理逻辑。
我找到了使用 lambda 并用一些通用逻辑包装此 lambda 来解决此问题的最佳方法。
考虑以下因素:
using System;
using System.Runtime.CompilerServices;
using static ConsoleApp.RuntimeUtility;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
try
{
Test();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
public static void Test()
{
Run("Error", () =>
{
throw new Exception("Exception");
});
}
public static int Test2()
{
return Run("Error", () =>
{
throw new Exception("Exception");
return 0;
});
}
public static Task Test3()
{
return RunAsync("Error", async () =>
{
await Task.Delay(100);
throw new Exception("Exception");
});
}
public static Task<int> Test4()
{
return RunAsync("Error", async () =>
{
await Task.Delay(100);
throw new Exception("Exception");
return 1;
});
}
}
public class RuntimeUtility
{
public static void Run(string errorMessage, Action action, [CallerMemberName] string name = null)
{
try
{
action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static T Run<T>(string errorMessage, Func<T> action, [CallerMemberName] string name = null)
{
try
{
return action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static async Task RunAsync(string errorMessage, Func<Task> action, [CallerMemberName] string name = null)
{
try
{
await action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static async Task<T> RunAsync<T>(string errorMessage, Func<Task<T>> action, [CallerMemberName] string name = null)
{
try
{
return await action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
}
}
我在最顶层进行日志记录,在其他任何地方我都使用 运行 方法,它用异常处理逻辑包装了 lambda,我可以将任何数据传递给 运行 方法以便在异常情况下使用。
还有一些可以减少代码编写的东西 - [CallerMemberName] 属性将具有调用方方法名称;还有 using static
.
更新: 添加了返回值和 async/await.
的示例
在任何方法中,您是否可以设置在异常处理过程中自动拾取的内容?
以下将向调用程序冒泡 ErrorMessage 和原始异常。
void Main()
{
string ErrorMessage = "FooBar";
try
{
throw new Exception();
}
catch (Exception ex)
{
throw new Exception(ErrorMessage, ex);
}
}
有没有办法在没有 Try/Catch/Re-Throw 的情况下复制它?
重述问题:
有没有什么办法让它(以任何方式)自动获取我指定的异常?
void Main()
{
string ErrorMessage = "FooBar";
throw new Exception();
}
所以我了解了抛出新异常的概念并提供了更多信息。我有兴趣找到一种方法,当发生异常时,它会自动获取自定义信息(“FooBar”),并且 returns Try/Catch/Re-Throw 完成的事情,没有 Try/Catch 和重新投掷。
** 已编辑 **
当无需重新抛出而自然生成的异常到达 errorHandler 时,我希望能够检索我的 ErrorMessage(比如 ex.data?),其中包含“FooBar”。
void ErrorHandler(Exception ex)
{
Log(ex.Data); // ex.Data is set to "FooBar";
}
“例外系统如何知道您希望在例外中包含哪些自定义数据?”
这是我提问的基础。我能用它知道什么? :P
另一个有助于表达我正在寻找的想法:
public class CustomException : Exception
{
public CustomException() { }
public CustomException(string message) : base(message) { }
public CustomException(string message, Exception inner) : base(message, inner) { }
public string ErrorMessage { get; set;}
}
void Main()
{
CustomException cEx = new CustomException {ErrorMessage = "FooBar"};
throw new Exception(); // This would be any arbitrary error, not one I'm throwing...
}
然后在 ExceptionHandler 事件中,可能会覆盖新异常的创建,如:
if (cEx != null)
{
// Use cEx in place of new Exception() as the error to fill to send
}
else
{
// Use new Exception() as the error to fill to send
}
“在我看来,您可能将日志记录与异常管理混淆了 - 看起来您想要自动收集的信息通常是您的日志记录策略的一部分。”
好的,假设你是对的。
所以,我不想每次进来都记录,我只想记录随机错误发生时的信息。假设我想知道任何传入参数在传入时以及在它们有机会更改之前的值。
错误的StackTrace会告诉我Method Name和Parameters的名称以及Parameters的TYPES。一切顺利。
但我找不到获取传入的值的方法,因为第一,我无法找到它们,第二,它们可能在发送后发生了变化。
显然我可以确保我不会更改输入的内容,但如果我无论如何都无法获取这些值,那也无济于事。
也许解决这个问题就能解决我关于如何处理错误的问题。
所以现在另一个问题是“如何仅在出现异常时记录任何传入参数的值?”
我的问题可能太具体了(我在这里问的问题不多,我还在学习这里的交互。)也许我应该问:
如果我想要一条由以下内容组成的错误消息:
"Error in myAssembly.GetStudentName(27)"
其中 27 是一个整数(可能是 StudentID),如果没有 Try/Catch/Rethrow 我怎么能做到呢?
我可以创建一串
"Error in myAssembly.GetStudentName(27)"
进入每个方法。我不能做的是在没有 Try/Catch 的任何异常情况下获取该字符串并对其执行任何操作。
如果我对你的理解正确,你希望避免在任何地方编写错误处理逻辑。
我找到了使用 lambda 并用一些通用逻辑包装此 lambda 来解决此问题的最佳方法。
考虑以下因素:
using System;
using System.Runtime.CompilerServices;
using static ConsoleApp.RuntimeUtility;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
try
{
Test();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
public static void Test()
{
Run("Error", () =>
{
throw new Exception("Exception");
});
}
public static int Test2()
{
return Run("Error", () =>
{
throw new Exception("Exception");
return 0;
});
}
public static Task Test3()
{
return RunAsync("Error", async () =>
{
await Task.Delay(100);
throw new Exception("Exception");
});
}
public static Task<int> Test4()
{
return RunAsync("Error", async () =>
{
await Task.Delay(100);
throw new Exception("Exception");
return 1;
});
}
}
public class RuntimeUtility
{
public static void Run(string errorMessage, Action action, [CallerMemberName] string name = null)
{
try
{
action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static T Run<T>(string errorMessage, Func<T> action, [CallerMemberName] string name = null)
{
try
{
return action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static async Task RunAsync(string errorMessage, Func<Task> action, [CallerMemberName] string name = null)
{
try
{
await action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
public static async Task<T> RunAsync<T>(string errorMessage, Func<Task<T>> action, [CallerMemberName] string name = null)
{
try
{
return await action();
}
catch (Exception e)
{
throw new Exception(errorMessage + " from method " + name, e);
}
}
}
}
我在最顶层进行日志记录,在其他任何地方我都使用 运行 方法,它用异常处理逻辑包装了 lambda,我可以将任何数据传递给 运行 方法以便在异常情况下使用。
还有一些可以减少代码编写的东西 - [CallerMemberName] 属性将具有调用方方法名称;还有 using static
.
更新: 添加了返回值和 async/await.
的示例