首页 > 解决方案 > 为什么要为这个配置类创建一个接口?

问题描述

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

现在我遇到了一种我没有得到的接口用法。这是关于配置的 ASP.NET Core 文档。特别是,在页面中,有人谈论使用 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)?

标签: c#oopasp.net-coredesign-patterns.net-core

解决方案


在只有一个应用程序的情况下,您说这没有意义是正确的。但是,在某些情况下可能会出现这种情况。

这里发生的是,首先,BookstoreDatabaseSettings绑定到配置部分。从技术上讲,这就是所有需要的。但是,这使用选项模式,这意味着您必须然后 injnectIOptions<BookstoreDatabaseSettings>IOptionsSnapshot<BookstoreDatabaseSettings>,而不是BookstoreDatabaseSettings直接。这意味着对 的依赖Microsoft.Extensions.Options,这不一定是坏事,但它仍然是依赖。

下一行然后将接口绑定到实际BookstoreDatabaseSettings实例,从IOptions<BookstoreDatabaseSettings>. 换句话说,您现在可以简单地注入接口,而不是IOptions<BookstoreDatabaseSettings. 同样,没有什么纪念意义的,但它抽象了Microsoft.Extensions.Options. 对于它的价值,你可以很容易地注册BookstoreDatabaseSettings而不是界面来获得同样的东西。然后,您将能够BookstoreDatabaseSettings直接注入,而无需依赖Microsoft.Extensions.Options.

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


推荐阅读