C# 以经过对象验证的方式跟踪所采取的行动?

C# 以经过对象验证的方式跟踪所采取的行动?,c#,C#,让我们面对现实吧,有些时候你可以简单地跟踪异常并在出现故障时报告这些异常,但大多数时候,当你在执行复杂的操作并处理一个没有构建的库时,你必须自己跟踪正在发生的一切,以便在出现问题时,你可以适当地报告它。否则,您可能会出现一些奇怪的错误,例如:“字符串不能为空”,并且没有更多的信息。。。然而,在您的代码中,可能会有数千行代码出现此错误,这将使解决此错误成为一场噩梦,更不用说向用户报告正确的详细信息了 让我们举一个小例子来说明这一点。。。假设您正在构建一个应用程序,该应用程序从其开发工作站获取IIS

让我们面对现实吧,有些时候你可以简单地跟踪异常并在出现故障时报告这些异常,但大多数时候,当你在执行复杂的操作并处理一个没有构建的库时,你必须自己跟踪正在发生的一切,以便在出现问题时,你可以适当地报告它。否则,您可能会出现一些奇怪的错误,例如:“字符串不能为空”,并且没有更多的信息。。。然而,在您的代码中,可能会有数千行代码出现此错误,这将使解决此错误成为一场噩梦,更不用说向用户报告正确的详细信息了

让我们举一个小例子来说明这一点。。。假设您正在构建一个应用程序,该应用程序从其开发工作站获取IIS的开发人员设置,并使用
Microsoft.Web.Administration
将其应用到某个服务器上。这将涉及多个对象,如
站点
应用程序池
应用程序
虚拟目录
,等等。。。可以包含多个属性值的

一旦进入服务器,您就必须获取开发人员设置的每个属性值,并将它们应用到实际的服务器上,这些操作中的任何一个都可能由于某种原因而失败

为了跟踪进度和/或故障以进行正确的报告,您必须实现自己的代码,因为
Microsoft.Web.Administration
库在其异常消息中没有提供很多详细信息

我一直这样做的方式是在“应用设置/前端”例程中保留一个本地日志,然后使用它来知道当出现故障时代码在哪里。。。大概是这样的:

try
{
    this.log.Add("Applying pool.Failure.AutoShutdownExe");
    pool.Failure.AutoShutdownExe = this.deployment.WebSite.VirtualDirectory.ApplicationPool.AutoShutdownExe;
    this.log.Add("Successfully applied pool.Failure.AutoShutdownExe");
    //.........
}
catch(exception ex)
{
    this.log.Add("Deploy failure! Fatal error occurred. " + Environment.Newline +
    "Type: " + ex.GetType().Name + Environment.Newline +
    "Message: " + ex.Messsage + Environment.Newline +
    "Stack Trace: " + Environment.Newline + ex.StackTrace);
    //.................
}
- Deployment starting... - ..... - ..... - Applying pool.Failure.AutoShutdownExe - Deploy failure! Fatal error occurred. Type: ArgumentNullException Message: String cannot be empty Stack Trace: ......... Line 35.. . 如果在上述点出现故障,则会产生一个非常好且易于阅读的日志,如下所示:

try
{
    this.log.Add("Applying pool.Failure.AutoShutdownExe");
    pool.Failure.AutoShutdownExe = this.deployment.WebSite.VirtualDirectory.ApplicationPool.AutoShutdownExe;
    this.log.Add("Successfully applied pool.Failure.AutoShutdownExe");
    //.........
}
catch(exception ex)
{
    this.log.Add("Deploy failure! Fatal error occurred. " + Environment.Newline +
    "Type: " + ex.GetType().Name + Environment.Newline +
    "Message: " + ex.Messsage + Environment.Newline +
    "Stack Trace: " + Environment.Newline + ex.StackTrace);
    //.................
}
- Deployment starting... - ..... - ..... - Applying pool.Failure.AutoShutdownExe - Deploy failure! Fatal error occurred. Type: ArgumentNullException Message: String cannot be empty Stack Trace: ......... Line 35.. . -部署正在启动。。。 - ..... - ..... -正在应用pool.Failure.AutoShutdownExe -部署失败!发生了致命错误。 类型:ArgumentNullException 消息:字符串不能为空 堆栈跟踪: ......... 第35行。 这非常有效,因为我可以很容易地看到它失败的地方,但我觉得我花了大部分时间编写这些日志条目,而不是实际编写功能本身,我想知道是否有更简单的方法来做到这一点?例如,通过使“对象”成为“自我感知对象”,跟踪其上次访问的属性,然后用于以后报告或其他内容,从而将此跟踪功能移动到“对象”本身

那么你通常做什么?
-不要罗嗦地跟踪,只是脱口而出错误,就这样?
-以类似于我上面所做的方式进行详细跟踪?
-完全不同的东西


有没有一种标准且经验证的方法可以减轻开发人员的负担?

我想,在编程时,您会发现编写一个基本版本的程序来实现您想要的功能非常简单,然后您会将大部分时间花在“防御性编程”上—检查常见的异常,检查可能需要抛出异常、验证输入等的条件。作为一个例子,请看一看。虽然日志记录是一件好事,但在单元测试、集成测试和,确保你的输入被消毒,所以你的意思是,这是正常的,一旦你在这里呆了很长一段时间,它就会出现在你的地盘上。。。您花更少的时间编写功能,花更多的时间处理错误并向用户报告“漂亮”消息。。。很公平。但是,在C#中是否有一种“标准”的方法可以帮助程序员更快、更容易地完成这项工作?这正是我要说的。我不知道有什么“标准”。可能有一些库使用反射来检测属性更改,并提供一个可以插入的接口来记录这些更改。如果没有图书馆,你可以写一个。但执行防御性编码仍将取决于您。我不确定它是否适合您的情况,但我最多会重构代码以获得较小的类和方法,并正常依赖堆栈跟踪。我建议阅读Robert C. Martin的《干净代码》,如果你认为这种方法对你有帮助。