这是一个愚蠢的问题,所以你必须原谅我,但我是一个自学成才的程序员,良好,干净的架构常常让我感到难过。我正在通过这样的问题学习:)
所以我必须编写一个数据访问类来与NoSQL数据库进行交互。麻烦的是,我们希望能够在以后更改我们的NoSQL平台,因此我需要尽可能地在我的类和实际数据访问之间建立这种依赖关系。
在我脑海中勾勒出这一点,我认为最好的方法是使界面有点像这样:
public interface INoSql
{
string ServerLocation
{
get; set;
}
string DatabaseName
{
get; set;
}
string CollectionName
{
get; set;
}
void SaveChanges(List<NoSqlItem> nsCollection);
}
然后为MongoDB创建一个特定的数据访问类
public class MongoDBConnection : IRealtimeDataAccess
{
string ServerLocation
{
get; set;
}
string DatabaseName
{
get; set;
}
string CollectionName
{
get; set;
}
public void SaveChanges(List<NoSqlItem> nsCollection)
{
MongoServer mServer = MongoServer.Create(this.ServerLocation);
MongoDatabase mDb = mServer.GetDatabase(this.DatabaseName);
MongoCollection<BsonDocument> mDbItemCollection = mDb.GetCollection<BsonDocument>(this.CollectionName);
mDbItemCollection.InsertBatch(nsCollection);
}
到目前为止简单 - 我所要做的就是确保使用数据访问层的任何类只引用接口,然后如果我们想要换到另一个NoSQL提供者,我所要做的就是重新编码新数据访问组件实现相同的接口吗?好吧,想一想,当我想使用它时问题就出现了。因为这显然不起作用:
INoSql noSQLConnection = new INoSql;
因为您无法实例化接口。
那么保持我的代码好看和松散的解决方案是什么?阅读它看起来好像一个答案是将它注入构造函数:
public class MyClass
{
private INoSql NoSql;
public myClass(INoSql NoSql)
{
this.NoSql = NoSql;
}
}
哪个看起来整洁,但这不仅仅取代了这个问题吗?因为当你创建MyClass时,你必须实例化一个实现INoSql的具体版本,是的,那将是一个MongoDBConnection - 或者其他什么 - 而不是一个松散耦合的类?
显然我错过了什么,但是什么?这个常见问题还有其他解决方案吗?
干杯, 马特
答案 0 :(得分:5)
您无需重新发明轮子。
根据我的观点,存储库设计模式将完成这项工作:
<强>更新强>
我忘记了“如何获得接口实现”的部分。
您将遵循存储库模式,创建接口或抽象类,稍后是NoSQL对象源的特定实现。
为了获得正确的实现,正如其他人所指出的,你可以使用一些框架,如:
最后,我想建议您 Common Service Locator 是一个好朋友,以便不直接依赖于特定的IoC / DI框架:
答案 1 :(得分:2)
查看IoC容器,例如Castle Windsor,SpringFramework.net和StructureMap。这就是他们要解决的问题。
答案 2 :(得分:2)
我同意Matias的存储库模式。您正在尝试解决的另一个问题是对数据库提供程序(在您的示例中为MongoDB)进行严格依赖。尽管真正能够交换数据访问并不像将其隐藏在接口后面那么简单,但是这样做的技术称为依赖注入,并且在MyClass代码中使用它的一种形式(构造函数注入)。
以下是依赖注入的概述:http://jamesshore.com/Blog/Dependency-Injection-Demystified.html
你是正确的,它将硬性依赖的问题推到了其他地方。幸运的是,有一些工具可以帮助我们连接和管理我们以后想要注入和使用的依赖项。这些被称为反转控制容器,它们允许您指定和解决代码中的依赖关系,并且通常在配置文件中。这是关于他们的SO问题:
https://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c
Autofac,StructureMap和Unity是我成功使用的一些。
希望这有帮助!
答案 3 :(得分:1)
您可以使用Unity或其他IoC容器来注册和实例化实现接口的对象。您的代码看起来像:
INoSql noSQLConnection = UnityContainer.Resolve<INoSql>();