类库应如何向用户/UI 呈现通知?
正常使用您正在编写的 .NET 库时,会发生或多或少预期的情况。您需要通知用户/UI/调用者此事件已发生,即使它是预期的且并非异常。你会:
A) 抛出异常,让 UI 捕获它并处理它。
B) 引发 UI 可以侦听的某种类型的事件。
C) 做其他事情
您会做以上哪一项?如果两者都有,您对于何时抛出异常和引发事件的指导方针是什么?各自的优点和缺点是什么?
编辑:
这是我面临的一个例子。我的库使用第三方应用程序来打印运输标签,方法是启动第三方应用程序并将 XML 文件作为参数传递,该文件作为批处理类型操作进行处理。如果第三方应用程序已被用户打开,则必须先将其关闭,然后我的库才能调用它进行批处理操作。我的库检查应用程序是否正在运行,如果是,它只是停止并需要通知用户他们应该关闭第三方应用程序并重试。我完全希望这种情况发生作为图书馆正常使用的一部分。抛出异常,还是引发事件?
Something occurs that is more or less expected with normal use of a .NET library you are writing. You need to notify the user/UI/caller that this event has occurred, even though it is expected and not exceptional. Do you:
A) Throw an exception, let the UI catch it and deal with it.
B) Raise some type of event that the UI can listen for.
C) Do something else
Which of the above do you do? If both, what are your guidelines for when to throw an exception vs. raise an event? What are the pros and cons of each?
Edit:
Here is an example I'm facing. My library uses a third party application to print shipping labels by starting the third party application and passing an XML file as an argument, which is processed as a batch type operation. If the third party application is already open by a user, it must be shut down before my library can call it for the batch operation. My library checks to see if the application is running, and if it is, it simply stops and needs to notify the user that they should close the third party application and try again. I fully expect this to happen as part of the normal use of the library. Throw an exception, or raise an event?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这听起来确实像是事件是最合适的方法。除非你有一个无法实现其主要目的的方法,否则我不明白为什么异常是正确的做事方式。
一般来说,“通知”应该建议一个事件...
如果您可以提供更多您正在考虑的情况的示例 - 特别是任何您倾向于例外的情况 - 我们也许能够帮助更多。
This certainly sounds like something where an event is the most appropriate approach. Unless you've got a method which can't fulfil its main purpose, I can't see why an exception would be the right way of doing things.
In general "notification" should suggest an event...
If you can give more examples of the kind of situation you're thinking of - particularly any where you would lean towards an exception - we may be able to help more.
异常与事件不同,因为您必须处理它们。
如果您认为客户端代码无法继续,请抛出 >异常(例如:网络错误、安全错误、输入错误)。否则,请通过引发事件来确认发生了某些事情,但不要强迫调用者立即做出反应。
另请注意,事件可以异步引发和处理,并且不绑定到特定调用者的操作,而异常总是在特定方法调用的上下文中抛出。当然,您可以从任何地方抛出异常,但如果客户端代码不希望它们发生在它们发生的地方,那么它们实际上会变得毫无用处,因为未经处理。
另请参阅此线程。
至于您的情况:
显然,在您的情况下,除非第三方应用程序关闭,否则工作流程无法继续,并且这种情况并不完全正常,这意味着它更多的是技术限制而不是真正的工作流程选项。您也不能让客户端代码忽略它。这符合异常立即响应的性质。
然而,这种情况也并非完全例外,因为在某种程度上它是已知的和预期的。
因此,我建议您这样做:
CanRunNow
属性来确定应用程序是否正在运行;Run
方法中,再次进行检查,如果这次CanRunNow
为false
,则抛出异常(现在这是意想不到的!)通过这种方式,您可以为客户端代码提供自由和责任来执行检查并保持安全,或者直接继续(可能会出现异常)。 无论您选择什么行为,请务必记录下来!
Exceptions are different from events because you have to handle them.
If you think the client code just can't go on, throw an exception (examples: network error, security error, bad input). Otherwise, kindly acknowledge that something has happened by raising an event but don't force the caller to react immediately.
Also note that events may be raised and handled asynchronously and are not bound to particular caller's actions, whereas exceptions always get thrown in context of a specific method call. Of course, you can throw exceptions from anywhere but if the client code doesn't expect them where they occur, they become essentially useless because unhandled.
See also this thread.
As for your situation:
Apparently, in your case workflow cannot continue unless the third-party application is closed, and this situation is not exactly normal, meaning it's more of a technical restriction than a true workflow option. You also can't let the client code just ignore it. This fits exceptions immediate-response nature.
However, it is also true that this situation is not all-exceptional because on some level it is known and expected.
Because of that, I suggest you do this:
CanRunNow
property that determines if application is running;Run
method (let's assume it's called so);Run
method, do the check again, and if this timeCanRunNow
isfalse
, throw an exception (now this is unexpected!)This way you give the client code freedom and responsibility to either do a check and stay safe, or to go right ahead (and possibly get an exception). Whatever behavior you choose, make sure to document it!
如果它是预期的,那么它就是一个事件。如果不是预期的,那就是例外。
只是不要让“C”“显示消息框”。
If its expected, then it's an event. If it's not expected, it's an exception.
Just don't let "C" be "showing a message box".
您说事件是预期(也就是说,不是例外),因此,我认为您已经回答了自己的问题......在我看来,绝对是B。
You say the event is expected (that is, is not exceptional) so therefore, I think you have answered your own question... Definitely B in my opinion.
您需要通知两件事:自定义事件和错误处理。
我同意其他答案,捕获异常,并将其作为一个事件委托给 GUI
There are 2 things you want to notify, custom events and error handling.
Im agree with the other answers, catch the exception, and delegate it, as an event, to the G.U.I.
在我的应用程序中,我使用一个包含与用户通信的方法的界面。
类似于:
顶层系统将其实例传递到需要它的类/方法中。
好处是我可以将报告与逻辑的实现分离。代码更容易测试和重用。根据环境的不同,报告以不同的方式实现:
In my applications I use an interface which contains methods for communication with user.
Somthing like:
The top level system passes an instance of this into the classes/methods that needs it.
The benefit is that I can decouple the reporting from the implementation of the logic. The code is easier to test and reuse. The reporting is implemented in different ways depending on the environment: