c# - 使用继承自相同接口(interface) Console .Net Core 的类进行依赖注入(inject)

标签 c# dependency-injection .net-core console-application

我正在开发一个 .Net Core 控制台应用程序,它有两个类(GenerateCsv、GenerateTxt),它们继承自同一接口(interface)(GenerateFile)。它们都采用 IReadFile、IWriteFile 接口(interface)作为构造函数参数。

我想使用依赖注入(inject)创建正确的类来生成文件并在完成时返回一个字符串值。

static void Main()
    {
        string result="Processed Nothing";

        Console.WriteLine("To Generate: \n");
        Console.WriteLine("1) English CSV File Type 1 \n"+
                          "2) Englsih Txt File Type 2 \n" +
                          "3) To Exit Type 3 \n");

        var userInput = Convert.ToInt32(Console.ReadLine());

        if (userInput == 10)
            Environment.Exit(0);

        var service = BuildDependencies.Build();

        Console.WriteLine("Started Generating");
        Console.WriteLine("Working, please wait");

        switch (userInput)
        {
            case 1:
                result = service.GetService<IGenerateFile>().GenerateFile();
                break;
            case 2:
                result = service.GetService<IGenerateFile>().GenerateFile();
                break;
        }
        Console.WriteLine(result);

构建依赖类

using Microsoft.Extensions.DependencyInjection;
public static class BuildDependencies
{
    public static ServiceProvider Build()
    {
        var services = new ServiceCollection()
            .AddTransient<IReadFile, ReaFile>()
            .AddTransient<IWriteFile, WriteFile>()
            .AddTransient<IGenerateFile,GenerateCsv>()
            .AddTransient<IGenerateFile,GenerateTxt>()
            .BuildServiceProvider();

        return services;
    }

最佳答案

您应该用对工厂类的调用替换 switch(userinput) block 。

该类的契约可能类似于:

interface IFileGeneratorFactory
{
    // I used int because it's in your example code, but an enum would be a stronger contract
    IGenerateFile GetFileGenerator(int userInput);
}

其实现如下:

class FileGeneratorFactory : IFileGeneratorFactory
{
    readonly IServiceProvider serviceProvider;

    public FileGeneratorFactory(IServiceProvider serviceProvider)
        => this.serviceProvider = serviceProvider;

    public IGenerateFile GetFileGenerator(int userInput)
    {
        switch (userInput)
        {
            // The Factory has explicit knowledge of the different generator types,
            // but returns them using a common interface. The consumer remains
            // unconcerned with which exact implementation it's using.
            case 1:
                return serviceProvider.GetService<GenerateCsv>();
            case 2:
                return serviceProvider.GetService<GenerateTxt>();
            default:
                throw new InvalidOperationException($"No generator available for user input {userInput}");
        }
    }
}

注册类如下:

var services = new ServiceCollection()
    .AddTransient<GenerateCsv>()
    .AddTransient<GenerateTxt>()
    .AddTransient<IFileGeneratorFactory, FileGeneratorFactory>();

然后,消费如下:

IGenerateFile fileGenerator = service
    .GetService<IFileGeneratorFactory>()
    .GetFileGenerator(userInput);

string result = fileGenerator.GenerateFile();

这个工厂实现非常简单。我这样写是为了让它易于理解,但我强烈建议您查看 Simple Injector docs 中更优雅的示例。 。由于这些示例针对的是 Simple Injector,而不是 ASP.Net DI,因此它们可能需要进行一些调整才能适合您,但基本模式应该适用于任何 DI 框架。

关于c# - 使用继承自相同接口(interface) Console .Net Core 的类进行依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54737304/

相关文章:

c# - Visual Studio - 创建面向 .Net Core 的类库

c# - 如何从 AuthorizationHandler .NET Core 获取参数

c# - MSTest 中的通用数据驱动单元测试

c# - 如何向数组添加关联索引。 C#

C# 正则表达式. 替换为现有单词

c# - 使用依赖注入(inject)管理 HttpClient 的多个实例

c# - 如何验证 ASP.NET Core 中的 DI 容器?

c# - 多个 Controller 之间的共享方法 C# MVC4

c# - 团结与委托(delegate)

.net - .NET 核心 Web API 中是否有取消调用的方法?