C# 使用继承自同一接口控制台.Net内核的类进行依赖注入
我正在开发一个.Net核心控制台应用程序,它有两个类(GenerateCsv、GenerateText),它们继承自同一个接口(GenerateFile)。它们都将IReadFile、IWriteFile接口作为构造函数参数 我想使用依赖项注入创建正确的类来生成文件,并在完成时返回字符串值C# 使用继承自同一接口控制台.Net内核的类进行依赖注入,c#,dependency-injection,.net-core,console-application,C#,Dependency Injection,.net Core,Console Application,我正在开发一个.Net核心控制台应用程序,它有两个类(GenerateCsv、GenerateText),它们继承自同一个接口(GenerateFile)。它们都将IReadFile、IWriteFile接口作为构造函数参数 我想使用依赖项注入创建正确的类来生成文件,并在完成时返回字符串值 static void Main() { string result="Processed Nothing"; Console.WriteLine("To Gener
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);
static void Main()
{
string result=“未处理”;
Console.WriteLine(“生成:\n”);
Console.WriteLine(“1)英文CSV文件类型1\n”+
“2)英语Txt文件类型2\n”+
“3)退出类型3\n”);
var userInput=Convert.ToInt32(Console.ReadLine());
如果(userInput==10)
环境。退出(0);
var service=BuildDependencies.Build();
Console.WriteLine(“已开始生成”);
Console.WriteLine(“正在工作,请稍候”);
开关(用户输入)
{
案例1:
结果=service.GetService().GenerateFile();
打破
案例2:
结果=service.GetService().GenerateFile();
打破
}
控制台写入线(结果);
类构建依赖项
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;
}
使用Microsoft.Extensions.DependencyInjection;
公共静态类BuildDependencies
{
公共静态ServiceProvider生成()
{
var services=newservicecolection()
.AddTransient()
.AddTransient()
.AddTransient()
.AddTransient()
.BuildServiceProvider();
返回服务;
}
您可以创建两个接口
interface IGenerateCsv : IGenerateFile{}
interface IGenerateTxt: IGenerateFile{}
然后向您的DI提供商注册这两项服务:
public static ServiceProvider Build()
{
var services = new ServiceCollection()
.AddTransient<IReadFile, ReaFile>()
.AddTransient<IWriteFile, WriteFile>()
.AddTransient<IGenerateCsv ,GenerateCsv>()
.AddTransient<IGenerateTxt,GenerateTxt>()
.BuildServiceProvider();
return services;
}
然后注册IFileGenerator
public static ServiceProvider Build()
{
var services = new ServiceCollection()
.AddTransient<IReadFile, ReaFile>()
.AddTransient<IWriteFile, WriteFile>()
.AddTransient<IGenerateCsv ,GenerateCsv>()
.AddTransient<IGenerateTxt, GenerateTxt>()
.AddTransient<IFileGenerator, FileGenerator>()
.BuildServiceProvider();
return services;
}
这是假设您有某种消费类。如果您只是在使用Main方法,请执行以下操作:
var serviceProvider = BuildDependencies.Build();
var fileGenerator = serviceProvider.GetService<IFileGenerator>();
var serviceProvider=BuildDependencies.Build();
var fileGenerator=serviceProvider.GetService();
您应该将开关(userinput)
块替换为对factory类的调用
该类的契约可能类似于:
接口IFileGeneratorFactory
{
//我使用int是因为它在您的示例代码中,但enum将是一个更强大的契约
IGenerateFile GetFileGenerator(int userInput);
}
实施过程如下:
类FileGeneratorFactory:IFileGeneratorFactory
{
只读IServiceProvider服务提供商;
公共文件生成器工厂(IServiceProvider服务提供商)
=>this.serviceProvider=serviceProvider;
公共IGenerateFile GetFileGenerator(int userInput)
{
开关(用户输入)
{
//工厂对不同的发电机类型有明确的了解,
//但是使用公共接口返回它们。使用者仍然
//不关心它使用的具体实现。
案例1:
返回serviceProvider.GetService();
案例2:
返回serviceProvider.GetService();
违约:
抛出新的InvalidOperationException($“没有可用于用户输入的生成器{userInput}”);
}
}
}
按如下方式注册课程:
var services=newservicecolection()
.AddTransient()
.AddTransient()
.AddTransient();
然后,像这样消费:
IGeneratFile文件生成器=服务
.GetService()
.GetFileGenerator(用户输入);
字符串结果=fileGenerator.GenerateFile();
这个工厂实现非常简单。我这样写是为了保持它的可接近性,但我强烈建议查看中更优雅的示例。因为这些示例针对的是简单注入器,而不是ASP.Net DI,它们可能需要一些调整才能为您工作——但基本模式应该适用于任何DI框架。d谢谢,但我如何才能将FileGenerator类注入到我的使用者中?当我执行代码时,它会转到FileGeneratorFactory执行内部代码,但FileGenerator始终为空。您可能需要稍微调整服务注册--可能需要根据具体类型注册
GenerateCsv
和GenerateXT
而不是它们的接口。如果你找到了,请告诉我,我会更新示例以使其更加完整。如果你仍然卡住,我今天晚些时候会再次检查我的代码,看看缺少什么。谢谢,这很有效。但这是正确的方法吗?你的意思是,注册具体类型正确吗?在这种情况下,我会说它是正确的。DI容器在解析类型之前需要被告知类型。您可以添加唯一的接口(IGenerateCV
/IGeneratext
)并使用这些接口进行注册/解析,但我认为当您仅通过工厂解析它们时,这不会给您带来任何好处。我已经更新了我的答案,以包含一个注册示例。
class Consumer
{
private readonly IFileGenerator fileGenerator;
Consumer(IFileGenerator, fileGenerator)
{
this.fileGenerator = fileGenerator;
}
public void SomeMethod(string userInput)
{
switch(userInput)
{
case 1:
fileGenerator.GenerateFile(OutputType.Csv);
break;
case 2:
fileGenerator.GenerateFile(OutputType.Text);
break;
default:
break;
}
}
}
var serviceProvider = BuildDependencies.Build();
var fileGenerator = serviceProvider.GetService<IFileGenerator>();