正如標題所說,我有一個 .NET Core 應用程式,我正在嘗試將其轉換為并利用內置的 Microsoft 依賴注入。
我有一個物件和該物件的基類,將其稱為CommunicationBase和Communicator. 當我的應用程式啟動并讀取組態檔時,我可以實體化 N 個物件。
以前,在切換到依賴注入之前,在我讀取組態檔的啟動例程中的某個地方,我會有一個List<CommunicationBase>變數,我將實體化并向其中添加Communicator物件,同時設定一些基本屬性,這些屬性基于關于我的配置中有多少以及配置中的每個屬性。
我將如何通過 DI 實作這一目標?
我知道在我的服務中,我會注冊型別,以便它可以注入其他類建構式。
例如,services.AddTransient<CommunicationBase, Communicator>();但據我所知,這只是向 DI 注冊型別。我可以將它注入到一個類中,并擁有其中一個的隨機實體。
那么我將如何擁有 N 個實體并能夠在創建實體時設定每個實體的屬性?
或者,在這種情況下,DI 不是必需的或不起作用,而我只需要按照以前的方式進行操作?
謝謝!
uj5u.com熱心網友回復:
我會稍微修改這里顯示的方法。所以我會定義一些列舉,然后用來決定回傳哪個實體。
示例類設定和列舉:
public enum CommuniationType
{
False, True, Other,
}
public abstract class CommunicationBase
{
public CommunicationBase(CommuniationType communiationType)
{
CommuniationType = communiationType;
}
public bool IsConnected { get; set; }
public CommuniationType CommuniationType { get; protected set; }
}
public class Communicator : CommunicationBase
{
public Communicator(CommuniationType communiationType) : base(communiationType) { }
}
現在,在您可以訪問服務集合的地方(例如在 ASP.NET 中,該地方將是Stratup.RegisterServices方法)您定義具體類的物件并注冊它們,如下面的示例代碼(在底部,還有測驗使用CommunicationBase物件進行測驗的類):
public class Program
{
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
SetupNObjects(serviceCollection);
serviceCollection.AddTransient<CommunicationBaseServiceResolver>(serviceProvider => communicationType =>
{
var implementations = serviceProvider.GetServices<CommunicationBase>();
return implementations.First(x => x.CommuniationType == communicationType);
});
serviceCollection.AddScoped<FalseTestClass>();
serviceCollection.AddScoped<TrueTestClass>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var f = serviceProvider.GetService<FalseTestClass>();
var t = serviceProvider.GetService<TrueTestClass>();
}
// Here you should take care of registering objects, after reading config.
// That would be best place to do that.
static void SetupNObjects(ServiceCollection serviceCollection)
{
var comFalse = new Communicator(CommuniationType.False);
comFalse.IsConnected = false;
var comTrue = new Communicator(CommuniationType.True);
comTrue.IsConnected = true;
serviceCollection.AddScoped<CommunicationBase>((serviceProvider) => comFalse);
serviceCollection.AddScoped<CommunicationBase>((serviceProvider) => comTrue);
}
}
public class FalseTestClass
{
private readonly CommunicationBase communication;
public FalseTestClass(CommunicationBaseServiceResolver resolver)
{
communication = resolver(CommuniationType.False);
}
}
public class TrueTestClass
{
private readonly CommunicationBase communication;
public TrueTestClass(CommunicationBaseServiceResolver resolver)
{
communication = resolver(CommuniationType.True);
}
}
uj5u.com熱心網友回復:
首先,您是否需要清楚 Transient、Scoped、Singleton 生命周期之間的區別。了解如何使用將從您的組態檔中讀取的 Communicator 物件串列。
解決您的問題的一種方法是
- 使用一種方法創建一個介面 ICommunicatorList 以獲取串列,我的意思是您可以包含通信者串列。
- 創建一個繼承自 ICommunicatorList(例如稱為 CommunicatorList)的類,其中包含一個用于您的 Communicator 串列的私有欄位。在建構式方法中,使用通信器串列設定您的私有欄位,o 在這里,您可以從組態檔的部分接收引數,以迭代和填充您的私有欄位。
- 在這個類上實作您的代碼以回傳通信器串列。
- 現在,在您的啟動檔案中,您現在可以創建服務 services.AddTransient< ICommunicatorList>(x => new CommunicatorList(parameters));
uj5u.com熱心網友回復:
我會按照以下方式進行。
首先你有通信器和設定類:
namespace WebApiApp
{
public abstract class CommunicationBase
{
public abstract string Communicate();
}
public class Communicator1Settings
{
public string Parameter { get; set; }
}
public class Communicator1 : CommunicationBase
{
private readonly string parameter;
public Communicator1(string parameter)
{
this.parameter = parameter;
}
public override string Communicate()
{
return $"Type: {nameof(Communicator1)}, parameter: {this.parameter}";
}
}
public class Communicator2Settings
{
public string Parameter1 { get; set; }
public string Parameter2 { get; set; }
}
public class Communicator2 : CommunicationBase
{
private readonly string parameter1;
private readonly string parameter2;
public Communicator2(string parameter1, string parameter2)
{
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
public override string Communicate()
{
return $"Type: {nameof(Communicator1)}, parameter1: {this.parameter1}, parameter2: {this.parameter2}";
}
}
public class CommunicatorsSettings
{
public List<Communicator1Settings> Communicators1 { get; set; }
public List<Communicator2Settings> Communicators2 { get; set; }
}
}
在 appsettings.json 中,您有通信器的配置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Communicators": {
"Communicators1": [
{
"Parameter": "First communicator1 parameter"
},
{
"Parameter": "Second communicator1 parameter"
}
],
"Communicators2": [
{
"Parameter1": "First communicator2 parameter1",
"Parameter2": "First communicator2 parameter2"
},
{
"Parameter1": "Second communicator2 parameter1",
"Parameter2": "Second communicator2 parameter2"
}
]
}
}
所以你有兩個Communicator1不同引數的實體和兩個不同引數的實體Communicator2。
然后,您配置容器。以下是program.cs.net 6的內容:
using WebApiApp;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
AddCommunicators();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
void AddCommunicators()
{
var settings = new CommunicatorsSettings();
builder.Configuration.Bind("Communicators", settings);
foreach (var communicatorSettings in settings.Communicators1)
{
builder.Services.AddScoped<CommunicationBase>(
_ => new Communicator1(communicatorSettings.Parameter));
}
foreach (var communicatorSettings in settings.Communicators2)
{
builder.Services.AddScoped<CommunicationBase>(
_ => new Communicator2(communicatorSettings.Parameter1, communicatorSettings.Parameter2));
}
}
現在你可以注入IEnumerable<CommunicationBase>你的控制器:
using Microsoft.AspNetCore.Mvc;
namespace WebApiApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class CommunicatorsController : Controller
{
private readonly IEnumerable<CommunicationBase> communicators;
public CommunicatorsController(IEnumerable<CommunicationBase> communicators)
{
this.communicators = communicators;
}
public IActionResult Get()
{
var result = this.communicators.Select(x => x.Communicate());
return this.Json(result);
}
}
}
這是/communicatorsWeb API的結果:
[
"Type: Communicator1, parameter: First communicator1 parameter",
"Type: Communicator1, parameter: Second communicator1 parameter",
"Type: Communicator1, parameter1: First communicator2 parameter1, parameter2: First communicator2 parameter2",
"Type: Communicator1, parameter1: Second communicator2 parameter1, parameter2: Second communicator2 parameter2"
]
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/397986.html
上一篇:多個條件與ifelse
下一篇:如何在Linq中將行轉換為列
