我正在用C#开发一个应用程序,该应用程序基本上是一个接口,该接口可以(最有可能)通过REST API接收数据或将数据返回到各种外部应用程序/客户端。应充分灵活地设计应用程序,以便仅通过更改配置文件即可换出后端数据存储以指向新的数据存储,或者可能在可用数据存储之间循环以在不同格式的数据存储上查找数据。数据的总体结构大致是一个文件系统/树,其中自定义数据附加到某些节点上以进行搜索,权限...等。
例如,我们可能会在SQL DB中提供实时生产数据,但有可能会将一些旧数据存储在网络共享中平整的csv文件中,并且希望接口的新实现能够将来会包含在内(这些的数据库实现将已经定义,这意味着如果某个东西的GUID类型的pkid,我们将无法更改。)
我在计划中存在的问题是这些后端数据格式具有不同的唯一ID ...等。因此,接口可能具有以下方法:
public long CreateFolder(long parent, string folderName);
这对于使用整数或长ID的东西可以很好地工作,但是如果CreateFolder操作的返回是GUID或文件名(字符串),则接口实现的使用者将遇到问题。还希望尽可能少地更改“业务逻辑”层,并在最低级别的数据层进行更改。
我的第一个想法是创建所有返回字符串的接口,并让数据层实现将字符串转换为本机数据类型,但这对我来说似乎很丑。
关于这种事情的任何指导吗?
编辑:要添加的是我用于DB接口的模式。
现在,我倾向于使用string,int和long重载所有接口,然后在接口实现中处理转换/转换。
答案 0 :(得分:0)
您需要抽象出差异。简单来说,将签名更改为:
FROM python:3.6-stretch
RUN python3.6 --version && pip3 --version
RUN pip3 install gunicorn
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
RUN mkdir /code
COPY . /code
WORKDIR /code
RUN pip3 install --no-cache-dir -r ./requirements.txt
ADD ./boot.sh /usr/local/bin/boot.sh
RUN chmod u+x /usr/local/bin/boot.sh
ENTRYPOINT /usr/local/bin/boot.sh
将IFolder定义为C#接口,如下所示:
public IFolder CreateFolder(long parent, string folderName);
每种后端数据格式将需要其自己的具体类,该类继承并实现IFolder。 CreateFolder调用者确实也知道它在谈论哪个具体的后端类,因为它只能看到抽象的IFolder接口。
答案 1 :(得分:0)
要求:
解决方案:
在您的情况下,我认为使用存储库模式和决定要使用哪个存储库的某些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>
{
}
答案 2 :(得分:0)
我建议您一个可能的解决方案:
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> { }
这可能吗?