[英]How to resolve dependency injection with class constructor that takes two implementations of the same interface
I only know basics of IoC.我只知道 IoC 的基础知识。 For the sake of simplicity (uhh), I want to stay with
Microsoft.Extensions.DependencyInjection
.为了简单起见(呃),我想继续使用
Microsoft.Extensions.DependencyInjection
。
The IProcessor
interface (and IData
one which I don't detail and is implemented by Excel
and SQLServer
classes): IProcessor
接口(和IData
接口,我没有详细说明,由Excel
和SQLServer
类实现):
public interface IProcessor
{
List<FielModel> ReadFieldsFromExcel();
List<FieldModel> ReadFieldsFromSQLServer();
}
The Processor
implementation: Processor
实现:
public class Processor : IProcessor
{
private readonly IData _excel;
private readonly IData _sqlServer;
public Processor(IData excel, IData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
public List<FielModel> ReadFieldsFromExcel();
{
// ..
}
public List<FieldModel> ReadFieldsFromSQLServer();
{
// ..
}
}
The main Program
with the DI.主要
Program
与DI。
class Program
{
private static ServiceProvider _serviceProvider;
static void Main(string[] args)
{
RegisterServices();
var processor = _serviceProvider.GetService<IProcessor>();
// ..
}
private static void RegisterServices()
{
// Setups dependency injection
var service = new ServiceCollection()
.AddSingleton<IProcessor, Processor>()
.AddSingleton<IData, Excel>()
.AddSingleton<IData, SQLServer>()
.AddSingleton<Program>();
_serviceProvider = service.BuildServiceProvider();
}
}
The problem is that both excel
and slqServer
are instantiated to SQLServer
(ie the last IData
registered singleton).问题是
excel
和slqServer
都被实例化为SQLServer
(即最后一个IData
注册的单例)。 How can I resolve this instatiation via dependency injection?如何通过依赖注入解决此实例化问题?
I already found a way to instantiate specific class the following way, but I don't think it is directly (and implicitly) applicable to a class constructor...我已经找到了一种通过以下方式实例化特定类的方法,但我不认为它直接(和隐式)适用于类构造函数......
var excel = _serviceProvider.GetServices<IData>()
.First(o => o.GetType() == typeof(Excel));
Thanks for any insights.感谢您提供任何见解。
You could register a delegate:您可以注册一个代表:
var service = new ServiceCollection()
.AddSingleton<Excel>()
.AddSingleton<SQLServer>()
.AddSingleton<IProcessor>(provider =>
new Processor(
provider.GetRequiredService<Excel>(),
provider.GetRequiredService<SQLServer>())
.AddSingleton<Program>();
The simplest way is to declare a marker interface for each specific implementation:最简单的方法是为每个特定实现声明一个标记接口:
public interface IExcelData : IData { /* nothing */ }
public class Excel : IExcelData { ... }
public interface ISqlServerData : IData { /* nothing */ }
public class SqlServer : ISqlServerData { ... }
public class Processor : IProcessor
{
private readonly IData _excel;
private readonly IData _sqlServer;
public Processor(IExcelData excel, ISqlServerData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
...
}
services
.AddSingleton<IExcelData, Excel>()
.AddSingleton<ISqlServerData, SQLServer>()
...
BTW, instead of manually creating the dependency containers, you should look into using the generic host: https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host顺便说一句,您应该考虑使用通用主机,而不是手动创建依赖项容器: https : //docs.microsoft.com/en-us/dotnet/core/extensions/generic-host
You could also inject an IEnumerable<YourDependency>
if the two concrete types are registered against the same interface.如果两个具体类型是针对同一接口注册的,您还可以注入
IEnumerable<YourDependency>
。
public class Processor : IProcessor
{
private readonly IEnumerable<IData> _dataDependencies;
public Processor(IEnumerable<IData> dataDependencies)
{
_dataDependencies= dataDependencies;
}
}
You could then resolve the relevant type by having some sort of Enum on the implementing class that you can use to select the appropriate service.然后,您可以通过在实现类上使用某种 Enum 来解析相关类型,您可以使用它来选择适当的服务。 I will use a simple string example to illustrate.
我将使用一个简单的字符串示例来说明。 (you probably shouldn't do it this way)
(你可能不应该这样做)
public class Processor : IProcessor
{
private readonly IEnumerable<IData> _dataDependencies;
public Processor(IEnumerable<IData> dataDependencies)
{
var selectedDependency = dataDependencies.FirstOrDefault(dep => dep.Type == "Excel");
}
}
Please try this.请试试这个。
var excel = _serviceProvider.GetServices<Excel.IData>();
After reading comment .看完评论。
You can change constructor as following.您可以按如下方式更改构造函数。
public Processor(Excel.IData excel, SQLServer.IData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.