我刚刚读到了c#中的存储库模式。它将为实际数据的访问方式提供可互换的层。那很棒。但是,请考虑以下事项:
我有一个XmlPersonRepository,它将从文件中获取XML数据并将其作为c#对象返回(Person.cs POCO)。现在我希望XML数据的物理源也可以互换。最初,它来自一个文件,但它也可以来自Web服务器或资源字符串。我将如何以最可重用的方式实现此功能?我不想写像XmlPersonFromFileRepository和XmlPersonFromWebRepository这样的东西,因为它意味着代码重复。它会复制用于将原始XML数据转换为c#对象的代码,但无论是从文件还是从Web服务获取XML,此代码都保持不变。因此,在两个类中都有转换代码是多余的。
简而言之,我希望有两个抽象层:一个层从任何源获取psysical XML数据,另一个层将此数据转换为c#对象。两者都应该是可以互换的。
我该如何实现?请告诉我这是不是一个好主意,我是否走在正确的轨道上?
答案 0 :(得分:1)
简单。你只是在你的问题中措辞。
您有两个问题需要解决:
实施第一个问题: - IXmlDataGetter,一个从源获取单个XML数据的接口。
public interface IXmlDataGetter {
XmlData GetData(XmlDataName name);
}
" XMLDATA"应该是byte []或Stream(因为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解析数据并显式构建对象。您只需创建一个执行te作业的类,并将适当的策略作为构造函数参数:
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数据。
答案 1 :(得分:0)
如上所述,检查依赖注入/ Ioc是什么,并查看一些框架(如Ninject,Autofac等)。
简而言之,您应该创建一个接口IXmlPersonRepository
来定义您的方法,然后在所有不同的类上实现它,它将为您提供像
等等。
然后,您将使用接口IXmlPersonRepository来进行调用。 DI位将负责接口的具体实现,并且可以很容易地在db,file等之间进行交换。