【问题标题】:Interface definition for encapsulating a generic data source [closed]用于封装通用数据源的接口定义 [关闭]
【发布时间】:2018-02-28 13:55:43
【问题描述】:

我目前正在研究基于 C# 插件的设计,其中插件 API 方法可以访问 Context 对象,该对象将包含该方法工作所需的相关信息。在当前实现中,文件路径被配置为 Context 属性之一,因为它必须在解析文件并加载 API 中的其他方法将使用的信息层次结构时提供给主要方法之一。但是 Context 接口中所需的灵活性是能够容纳各种各样的数据源,而不仅仅是基于文件的数据源,例如稍后,现在以文件形式出现的数据可能会被基于 DB 的数据源或网络流或 Web 服务调用返回的 JSON 数据替换。当前界面为:

public interface IFlowContext : IPluginContext
{
    string FlowFilePath { get; set; }
    string FlowImportFilePath { get; set; }
}

我很难找到一个足够通用的基于数据源的接口定义来处理所需的灵活性。

有人有什么想法吗?

【问题讨论】:

  • 组合,而不是继承
  • the data that is coming in the form of a file now, might be replaced by a DB based data source or a network stream, or a JSON data returned by a web service invoke - 如果你想隐式处理它们,你必须弄清楚它们的共同点——或者你需要从它们那里得到什么。本质上,接口定义了实现之间的“通用”。这是一份合同。
  • 为通用功能设计接口,不要在接口中包含任何特定于实现的内容。如果您正在谈论将在运行时延迟加载的插件,则每个插件将需要不同的设置,因此插件将负责从配置文件加载设置,或者公开其自己的设置类,该类必须由调用填充以某种方式应用。如果您只是在组合根目录中实例化它们,那么只需使用下面@ScottHannen 回答中所述的 DI。

标签: c# design-patterns abstraction solid-principles


【解决方案1】:

答案是不要尝试创建一个足够“通用”的接口来满足您当前实现的设置和未来实现所需的设置。每个接口都应该为依赖它的类编写。您可能仍然会发现一些共同点,您可以重用其中的一些接口。例如,您可以有一个依赖于文件路径的类的不同实现。但是,如果两个不同的类依赖于两个不同的数据源,那么一个接口应该能够为它们两者提供设置,这是零原因的。

不要混淆 - 无论这些文件路径支持什么,应该是一个可重用的接口。但这些实现可能需要不同的设置。这需要文件路径。另一个可能需要数据库连接字符串或其他东西。但是这些实现不需要依赖一些通用接口。它们都应该依赖于“描述”每个单独实现所需的接口。

这与接口隔离原则有关。如果实现需要文件路径,它应该依赖于提供文件路径的接口。但是,如果实现不需要文件路径,那么它不应该依赖于提供它们的接口。

举例说明:

public interface IGetsSomeData
{
    Data GetSomeData();
}

public class GetsSomeDataFromAFile : IGetsSomeData
{
    private readonly IFilePathSettings _filePathSettings;

    public GetsSomeDataFromAFile(IFilePathSettings filePathSettings)
    {
        _filePathSettings = filePathSettings;
    }

    public DataGetSomeData()
    {
        // read data from a file using a file path
    }
}

public class GetsSomeDataFromSql : IGetsSomeData
{
    private readonly IDatabaseSettings _databaseSettings;

    public GetsSomeDataFromAFile(IDatabaseSettings databaseSettings)
    {
        _databaseSettings = databaseSettings;
    }

    public DataGetSomeData()
    {
        // execute a SQL query using a connection string
    }
}

IGetsSomeData 是一个通用接口。但是实现不需要共享依赖项。也许 SQL 实现甚至不需要接口——它可能只需要一个连接字符串。

【讨论】:

    猜你喜欢
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-24
    • 2012-05-20
    • 2012-02-02
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    相关资源
    最近更新 更多