我们为什么要为此配置类创建一个接口?

时间:2019-09-23 14:13:19

标签: c# oop asp.net-core design-patterns .net-core

我对接口的理解是它们定义了契约,而实现该接口的类则对契约进行签名。在这种情况下,我们可以将类设计为依赖于合同而不是具体的实现。这具有减少耦合,启用多态性等优点。

现在,我遇到了一种我没有得到的接口。这是来自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)?

1 个答案:

答案 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

接口在这里为您提供的是抽象实际的类实现。您可以将接口单独放在项目之间共享的库中,并将实际的类实现留给每个单独的项目。如果共享库仅依赖于接口,则提供的实际实现将无关紧要。但是,您也可以轻松地在项目之间共享类的实现。这只是一个视角问题。