【问题标题】:C# Interfaces rules of thumb for data types returned返回数据类型的 C# 接口经验法则
【发布时间】:2019-02-15 16:31:25
【问题描述】:

我正在用 C# 开发一个应用程序,它基本上是一个接口,可以通过(很可能)一个 REST API 向各种外部应用程序/客户端获取或返回数据。应用程序的设计应该足够灵活,以便后端数据存储可以通过仅更改配置文件以指向新的数据存储或可能循环通过可用数据存储以在不同格式的数据存储上查找数据来交换。数据的整体结构大致是一个文件系统/树,其中一些节点附加了自定义数据,用于搜索、权限等。

例如,我们可能在 SQL 数据库中拥有实时生产数据,但有可能一些旧数据会存储在网络共享上的扁平化 csv 文件中,并且希望接口的新实现包括在未来(这些的数据库实现已经被定义,这意味着如果某些东西有一个 GUID 类型的 pkid,我们不能改变它。)

我在计划中遇到的问题是这些后端数据格式具有不同的唯一 ID...等等。所以接口可能有一个方法:

public long CreateFolder(long parent, string folderName);

这对于使用整数或长 Id 的东西来说可以正常工作,但是如果 CreateFolder 操作的返回是 guid 或文件名(字符串),则接口实现的使用者会遇到问题。还希望尽可能少地更改“业务逻辑”层并在最低级别的数据层进行更改。

我的第一个想法是创建所有返回字符串的接口,并让数据层实现处理将字符串转换为本机数据类型,但这对我来说似乎很难看。

有类似的指导吗?

编辑:添加这是我用于数据库接口的模式。

https://softwareengineering.stackexchange.com/questions/301362/how-are-abstract-database-interfaces-written-to-support-multiple-database-types/301371

现在我倾向于使用 string、int 和 long 重载所有接口,然后在接口实现中处理转换/转换。

【问题讨论】:

  • interface foo { T3 CreateFolder<T1, T2, T3>(T1 parent, T2 folder); }
  • 这并没有让我更接近,我应该提到后端数据存储之一使用强类型的 WSDL 接口。所以它不是纯粹的查询代码。所以现在我会有这样的代码:parent = long.Parse(parent.ToString())

标签: c# interface


【解决方案1】:

您需要抽象出差异。最简单的方法是将签名更改为:

public IFolder CreateFolder(long parent, string folderName);

将 IFolder 定义为 C# 接口,如下所示:

public interface IFolder { // Example method to be implemented by inheritors. void EnumerateFiles(); }

每种后端数据格式都需要自己的具体类来继承和实现 IFolder。 CreateFolder 调用者也知道它在谈论哪个具体的后端类,因为它只看到抽象的 IFolder 接口。

【讨论】:

  • 我认为这基本上就是我要走的路,但是上面一层利用接口实现的业务逻辑仍然可能与返回的数据类型发生冲突,除非我遗漏了什么。如在 folder.id 有时需要很长,有时需要一个字符串。
【解决方案2】:

要求:

  1. 可以选择在不同来源中存储/获取数据
  2. 易于更改连接使用什么。

解决方案:

我认为在您的情况下,使用存储库模式和一些决定使用哪个存储库的 Fabric 会很好。此外,您可以将存储库创建为泛型,以便快速更改要使用的模型。

public class IRepository<T> where T : class
{
   T Save(T model);
   IEnumerable<T> Get(Expression... condition);
   //another methods.
}

DbRepository<T> :IRepository<T>
{
}
CsvRepository<T> :IRepository<T>
{
}

【讨论】:

    【解决方案3】:

    我建议你一个可能的解决方案:

    public abstract class AbstractController<T> : ApiController {
        [HttpPost] // Or GET
        [Route("createfolder")]
        public IHttpActionResult CreateFolder<T>(long parent, string foldername) {
            T result = YourClass.CreateFolder<T>(parent, foldername);
    
            return Ok(result);
        }
    }
    
    [RoutePrefix("api/sql")]
    public abstract class SqlController : AbstractController<long> { }
    
    [RoutePrefix("api/csv")]
    public abstract class SqlController : AbstractController<string> { }
    

    这是一种可能的方式吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多