如何在不同的类类型上实现总体接口

时间:2019-04-05 09:27:27

标签: c# .net interface

我正在尝试实现具有一些基本功能的界面,以修改多家计算机供应商的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 ...

所以我想我有两个问题:

  1. 有人能想到一种更好的方法吗?
  2. 如果不是(更合适的话)使用out paramsBiosErrorCode属性?

4 个答案:

答案 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);
        }
    }
}