0

我刚刚阅读了 C# 中的存储库模式。它将为如何访问实际数据提供一个可互换的层。那太棒了。但是,请考虑以下事项:

我有一个 XmlPersonRepository,它将从文件中获取 XML 数据并将其作为 ac# 对象(Person.cs POCO)返回。现在我希望 XML 数据的物理源也可以互换。最初,它来自文件,但也可以来自 Web 服务器或资源字符串。我将如何以最可重用的方式实现这一点?我不想写像 XmlPersonFromFileRepository 和 XmlPersonFromWebRepository 这样的东西,因为这意味着代码重复。它将复制用于将原始 XML 数据转换为 ac# 对象的代码,但无论我是从文件还是从 Web 服务获取 XML,此代码都保持不变。所以在两个类中都有转换代码是多余的。

所以简而言之,我想要有两个抽象层:一个从任何来源获取心理 XML 数据的层,另一个将这些数据转换为 c# 对象的层。两者应该可以互换。

我该如何实施?请告诉我这是否是个好主意,我在正确的轨道上吗?

4

2 回答 2

1

简单的。你只是在你的问题中措辞。

你有两个问题需要解决:

  • 从源获取 XML 数据
  • 将 XML 数据转换为 C# 对象

实现第一个问题: - IXmlDataGetter,一个从源获取单个 XML 数据的接口。



    public interface IXmlDataGetter {
      XmlData GetData(XmlDataName name);
    }

“XmlData”应该是一个字节[]或一个流(因为XML包含关于数据编码的元数据,我认为它应该保持在字节级别)或者是一个DOM树(如XmlNode)。您选择最适合您的解决方案。

“XmlDataName”是您识别存储数据的方式。数据有名称,无论它多么复杂。它可能只是字符串“PERSON”和整数 25,即 id。ID 为 25 的人的数据名称可能是一对(“PERSON”,25)。

这个接口,可以为 DB 实现:



    public class DBXmlDataGetter : IXmlDataGetter {
      XmlData GetData(XmlDataName name) {
        return ResultOfQuery("SELECT xml_text FROM " + name.first /* PERSON */ + " WHERE ID=" + name.second  /* 25 */); 
      }
    }

这个接口也可以为一个文件实现:



    public class FileXmlDataGetter : IXmlDataGetter {
      XmlData GetData(XmlDataName name) {
        return ContentsOfFile(name.first /* PERSON */ + "_" + name.second /* 25 */ + ".xml"); 
      }
    }

当然,“ResultOfQuery”和“ContentsOfFile”只是我留给你解决的事情的名称。对于 Web,以同样的方式从您的 XmlDataName 构建您的 URL。

现在。第二个问题,将 XML 转换为 C# 对象。您可以使用 XMLDeserializer,或使用 XMLReader 解析数据并显式构建您的对象。你只需要创建一个类来完成这项工作并将适当的策略作为构造函数参数:



    public class XmlPersonRepository {
      private readonly IXmlDataGetter _getter;

      public PersonFetcher(IXmlDataGetter getter) {
        _getter = getter;
      }

      Person GetFromId(int id) {
        var xmlData = _getter.GetData(new XmlDataName("PERSON", id));
        return ConvertToPerson(xmlData); 
      }
    }

我不会在这里讨论 IoC/依赖注入的哲学问题,但这是基本模式。进行转换的类只是进行转换。从头到尾执行用例所需的一切都从“上方”“注入”。

您分离了职责,现在您可以根据需要从用户复制/粘贴到文本框中自由地获取 XML 数据。

于 2013-02-14T12:48:40.707 回答
0

如前所述,检查 Dependency Injection/Ioc 是什么,并看看那里的一些框架(如 Ninject、Autofac 等)。简而言之,您应该创建一个IXmlPersonRepository定义您的方法的接口,然后在所有不同的类上实现它,这些类将为您提供 xml 之类的

  • XmlFilePersonRepository:IXmlPersonRepository
  • XmlDBPersonRepository:IXmlPersonRepository

等等。

然后,您将使用接口 IXmlPersonRepository 进行调用。DI 位将负责您的接口的具体实现,并且很容易在数据库、文件等之间进行交换。

于 2013-02-14T12:02:07.803 回答