我对接口的理解是它们定义了契约,而实现该接口的类则对契约进行签名。在这种情况下,我们可以将类设计为依赖于合同而不是具体的实现。这具有减少耦合,启用多态性等优点。
现在,我遇到了一种我没有得到的接口。这是来自ASP.NET Core文档中有关配置的信息。特别是in the page,有人在谈论使用ASP.NET Core设置MongoDB。
他们基本上定义了这样的类和接口:
namespace BooksApi.Models
{
public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings
{
public string BooksCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
public interface IBookstoreDatabaseSettings
{
string BooksCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
}
然后他们按如下方式使用它:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
我必须说我不明白。类型BookstoreDatabaseSettings
的对象可以用作设置的DTO。它们根本不提供任何功能。那么为什么要在中间引入一个接口呢?
我在这里看不到一种用法,而在另一种用法上可以使用。我在这里看不到为什么要尝试将其解耦,我根本看不到多态性的任何使用,而且我真的不明白这一点。
为什么在这种情况下,当处理ASP.NET Core中的设置时,人们直接使用接口而不使用具体的类(例如BookstoreDatabaseSettings
)?
答案 0 :(得分:8)
在仅一个应用程序的上下文中,您是正确的,这没有任何意义。但是,在某些情况下可能会。
这里发生的事情是,首先,BookstoreDatabaseSettings
被绑定到config部分。从技术上讲,这就是所需要的。但是,这使用了选项模式,这意味着您必须然后注射IOptions<BookstoreDatabaseSettings>
,IOptionsSnapshot<BookstoreDatabaseSettings>
等,而不是直接注射BookstoreDatabaseSettings
。这意味着对Microsoft.Extensions.Options
的依赖,虽然这不是一件坏事,但这仍然是一个依赖。
然后,下一行将接口绑定到实际的BookstoreDatabaseSettings
实例,该实例是从IOptions<BookstoreDatabaseSettings>
拉出的。换句话说,您现在可以简单地注入接口,而不是IOptions<BookstoreDatabaseSettings
。再说一次,没有什么大不了的,但是它抽象了Microsoft.Extensions.Options
的使用。对于它的价值,您可以像注册界面一样轻松地注册BookstoreDatabaseSettings
而不是界面。然后,您将能够直接注入BookstoreDatabaseSettings
,而无需依赖Microsoft.Extensions.Options
。
接口在这里为您提供的是抽象实际的类实现。您可以将接口单独放在项目之间共享的库中,并将实际的类实现留给每个单独的项目。如果共享库仅依赖于接口,则提供的实际实现将无关紧要。但是,您也可以轻松地在项目之间共享类的实现。这只是一个视角问题。