我想知道在处理.NET时,使用IoC模式的最佳实践是什么。
例如,我应该通过IoC容器创建SqlConnection
/OracleConnection
或其他任何提供程序,还是应该使用简单的new关键字?
将我的类与具体提供程序类型分开是否有任何价值(包括当我只想使用一种类型的提供程序时)?
我想知道在处理.NET时,使用IoC模式的最佳实践是什么。
例如,我应该通过IoC容器创建SqlConnection
/OracleConnection
或其他任何提供程序,还是应该使用简单的new关键字?
将我的类与具体提供程序类型分开是否有任何价值(包括当我只想使用一种类型的提供程序时)?
代码维护不仅仅是替换一个提供者。对我来说,依赖注入更多地是为了保持代码逻辑上的分离,从而使其更易于维护,而不是为了未来某个提供者更改时保证代码兼容性。
DI还可以更轻松地将一个项目中的代码重用到另一个项目中,因为它使各部分之间的依赖关系更加明确。
话虽如此,我从未使用过IOC容器,也从未看到需要使用它,因此无法对这个问题进行评论。
但是,您应该尽可能地从代码中删除隐式依赖项,以保持代码的可重用性、可维护性和正确性。
注入SqlConnection
或IDbConnection
是相当无用的,因为DbConnection是一个泄漏的抽象。你只能用它来调用存储过程或简单的SELECT * FROM VIEW
类型的查询。任何更复杂的查询都将根据SQL方言而异。
当将连接本身隐藏在更高级别的抽象后面时,例如IUserRepository
或某种类型,您将有更好的成功机会。该接口的默认实现可能是与MS SQL Server通信的SqlUserRepository
,或者是与Oracle通信的OracleUserRepository
。
更好的方法是远离低级别的ADO.NET DbConnection API,转向诸如LINQ to SQL或Entity Framework之类的O/RM。然后,您通常会拥有一个LinqToSqlUserRepository
。
请注意,在这种情况下,我仍在谈论XXXUserRepository
。接口仍然没有改变。换句话说:IUserRepository
不是一个泄漏的抽象。您可以替换此接口进行单元测试,而使用SqlConnection
几乎不可能。
控制反转(IoC)的存在是为了在现实中,尽管您想使用一种类型的提供程序,但有一天某些事情会发生变化,您可能需要一个次要适配器,因此最好使用IoC而不是使用new关键字创建对象。随着时间的推移(随着需求的变化),IoC提供了灵活性来改变事物。
即使是.NET类,使用IoC也是一个好的实践。这将允许您的代码仅与接口或基类绑定(如果可用)。不仅如此,您还可以使用IoC框架指定构造函数参数。这对于SqlConnection中的连接字符串可能非常有用。
我还应该提到,使用IoC并仅编写接口代码将使单元测试变得更加容易。特别是在处理DB连接时,这一点尤为真实。
如果您使用IDbConnection和所有其他类而不是具体类,则在单元测试中它可能具有价值。
除了IOC等内容之外,我实际上已经多次使用DbFactoryProvider(更多信息)创建连接和其他与数据库相关的对象,并通过ConnectionString读取提供程序。
与数据库相关的主要问题通常是您无法仅使用ANSI-SQL与数据库,因此尽管您与具体类分离,但sql并不可传输。 (例如,在MySql中限制或在Sql Server中的Over和Partition)。
关于DI / IOC以及其他与DB无关的内容,将类解耦并消除依赖项非常有用,并在单元测试时有所帮助,例如当您正在针对服务工作时。即使不在单元测试中,当您正在针对服务工作且另一个团队仍在开发服务时,也可以创建一个虚假的服务来解决您的问题(不是全部),以便您可以在真正的服务可用之前进行工作。
还有很多例子,但是与服务(数据库存储库/网络/授权/任何其他)对抗是最直接的增值。