我正在尝试实现具有一些基本功能的界面,以修改多家计算机供应商的BIOS设置。
到目前为止,我有以下内容:
public interface IBiosConfigurator
{
bool IsBiosPasswordSet();
bool ValidateBiosPassword(string password);
bool SetBiosPassword(string currentPassword, string newPassword);
T GetSetting<T>(string settingName, string password);
T GetSetting<T>(string settingName, string propertyName, string password);
bool SetSetting<T>(string settingName, T value, string password);
}
但是我很快就发现这种需求不足:
如果某件事确实失败了,我不知道为什么。密码错误吗?您尝试设置的值是否不允许?设置名称不存在吗?
每个制造商都有自己的错误显示方式:有些使用ints,有些使用uint,其他使用字符串,没有通用类型。
像bool IsBiosPasswordSet()
这样简单的方法都有失败的可能,这并不说明问题。
我想缓解每个制造商都有自己的错误设置方法(每个供应商都有不同的错误)的唯一方法是创建一个enum BiosErrorCode
并尝试将供应商代码与我维护的列表匹配每个实现IBiosConfigurator
的类。
但是我仍然需要返回某些东西产生的实际错误代码,尽管就方法声明而言,这对我来说似乎是可以的:
BiosErrorCode GetSetting<T>(string settingName, string password, out T value)
我真的不能这样说:
BiosErrorCode IsBiosPasswordSet(out bool passwordSet);
但是我想解决这个问题的唯一另一种方法是属性BiosErrorCode LastErrorCode
,它可以让我保持方法声明的原样,但感觉有点像PInvokes ...
所以我想我有两个问题:
out params
或BiosErrorCode
属性?答案 0 :(得分:0)
我认为Bios
是多余的。 ;)更重要的是:我认为如果出现问题,您将抛出自定义异常。在正常情况下,您的实现应只返回您期望的结果。因此,如果不是这种情况,那将是真正的例外,那就是例外。
它允许您隐藏特定于供应商的逻辑,以针对特定于供应商的实现创建那些例外。
答案 1 :(得分:0)
按照实体原则,类或接口不应在一个对象中涵盖很多无关的业务。
答案 2 :(得分:0)
如果失败,则在具体的类中引发标准化的异常(例如InvalidPasswordException),其细节是实现特定的,而不是尝试使用返回码或使用var。您可以在异常中包含更多详细信息,并且您的调用程序可以以更结构化的方式处理它们。
答案 3 :(得分:0)
如果发生任何错误,则应引发异常。从概念上讲,Interfcae附带有异常,并且您切勿抛出接口文档中未提及的任何内容。
这留下了一个开放的问题途径,一个在Exception中捕获得很差的问题。对于那些人,您应该有一个日志记录实现,其中实现类在传入的构造时获取一个记录器,并跟踪以后可能需要的所有技术细节。通常只写控制台,因为它可以很容易地重定向。还有更多用于日志记录的交互框架,实现类应该将记录器作为具有强大保留保证的接口。
在大多数情况下,这实际上取决于您的文档。
这里是一个例子:
public class PasswordExpection : Exception
{
public PasswordExpection(string msg) : base(msg) { }
}
public class BiosExpection : Exception
{
public BiosExpection(string msg, Exception inner) : base(msg, inner) { }
}
interface IBiosControl
{
/// <summary>
/// Checks if a password is set.
/// </summary>
/// <exception cref="PasswordExpection">if the concept of password does not apply</exception>
/// <exception cref="BiosExpection">if there was an execution error</exception>
/// <returns>Weather or not the password was set</returns>
bool IsPasswordSet();
}
public class MyBios : IBiosControl
{
private readonly Action<string> _logger;
public MyBios(Action<string> logger)
{
_logger = logger;
}
public bool IsPasswordSet()
{
try
{
_logger("MyBios IsPasswordSet Connecting To Bios...");
throw new NotImplementedException();
}
catch(Exception e)
{
throw new BiosExpection("Execution Error", e);
}
}
}