使用依赖项注入初始化主形式的接口



这是我的代码隐藏表单ExpressionOfNeeds

private readonly IExpressionOfNeeds _expressionOfNeeds;
public FrmExpressionOfNeeds(IExpressionOfNeeds expressionOfNeeds)
{
InitializeComponent();
_expressionOfNeeds = expressionOfNeeds;
}
private async void FrmExpressionOfNeeds_Load(object sender, EventArgs e)
{
GCData.DataSource = await _expressionOfNeeds.GetAllExpressionOfNeeds();
}

这是我在MainForm后面的代码

private readonly IExpressionOfNeeds _expressionOfNeeds;
private readonly IService2 _service2;
private readonly IService3 _service3;
//and so on and so forth
public XtraMain()
{
InitializeComponent();
}
private void bbtnExpressionOfNeeds_ItemClick(object sender, ItemClickEventArgs e)
{
FrmExpressionOfNeeds frme = new(_expressionOfNeeds)
{
Name = "FrmExpressionOfNeeds"
};
ViewChildForm(frme);
}
private void bbtnForm2_ItemClick(object sender, ItemClickEventArgs e)
{
Form2 frme = new(_service2)
{
Name = "Form2"
};
ViewChildForm(frme);
}
private void bbtnForm3_ItemClick(object sender, ItemClickEventArgs e)
{
Form3 frme = new(_service3)
{
Name = "Form3"
};
ViewChildForm(frme);
}

等等
,这是我在程序类后面的代码

static void Main()
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddScoped<XtraMain>();
services.AddSingleton<ISqlDataAccess, SqlDataAccess>();
services.AddSingleton<IExpressionOfNeeds, ExpressionOfNeeds>();
});
var host = builder.Build();
using (var serviceScope = host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var mainform = services.GetRequiredService<XtraMain>();
Application.Run(mainform);
}
}

问题是_expressionOfNeeds的值总是为null,我找不到初始化它的方法
Update
我有很多表单和很多接口
所以我只把它限制在一个示例中,所以代码不会太大。

您就快到了。您已经将表单和服务注册到DI容器中,但忘记将接口注入表单的构造函数中。

您必须将依赖接口添加到表单的构造函数(首选解决方案(,或者稍后在需要时从服务提供商获取它们的实例。

你可以在下面的帖子中找到一个循序渐进的例子:

  • 如何在WinForms中使用依赖项注入

假设您有一个依赖于IMyServieMainForm,那么您应该有一个这样的构造函数:

IMyService _myService;
public MainForm(IMyService myService)
{
_myService = myService;
}

然后,一旦您将MainFormIMyService注册到DI容器中,并从服务提供商处获得实例,一切都将按预期工作。这里是主要的切入点:

static class Program
{
public static IServiceProvider ServiceProvider { get; private set; }
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
var host = CreateHostBuilder().Build();
ServiceProvider = host.Services;
Application.Run(ServiceProvider.GetRequiredService<MainForm>());
}
static IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder()
.ConfigureServices((context, services)=>{
services.AddTransient<IMyService, MyService>();
services.AddTransient<MainForm>();
});
}
}

如果出于某种原因(如我在链接答案中所解释的(,您需要在不将服务实例注入构造函数的情况下获得服务实例,那么您可以使用Program.ServiceProvider.GetRequiredService<SomeFormOrService>()

我建议创建一个工厂来获得主表单所需的表单

public interface IFormFactory {
TForm Create<TForm>() where TForm : Form;
}

假设在这种情况下要创建的类型都源自Form

该实现将使用服务提供商来解决所提供的表单类型

public class FormFactory: IFormFactory {
private readonly IServiceProvider services;
public FormFactory(IServiceProvider services) {
this.services = services;
}
public TForm Create<TForm>() where TForm : Form {
return services.GetRequiredService<TForm>();
}
}

主表单需要依赖于工厂,以便它可以根据需要创建表单

//...
private readonly IFormFactory factory;
public XtraMain(IFormFactory factory) {
InitializeComponent();
this.factory = factory;
}
private void bbtnExpressionOfNeeds_ItemClick(object sender, ItemClickEventArgs e) {
FrmExpressionOfNeeds frme = factory.Create<FrmExpressionOfNeeds>();
frme.Name = "FrmExpressionOfNeeds";
ViewChildForm(frme);
}
private void bbtnForm2_ItemClick(object sender, ItemClickEventArgs e) {
Form2 frme = factory.Create<Form2>();
frme.Name = "Form2";
ViewChildForm(frme);
}
private void bbtnForm3_ItemClick(object sender, ItemClickEventArgs e) {
Form3 frme = factory.Create<Form3>();
frme.Name = "Form3";
ViewChildForm(frme);
}
//...

确保服务提供商要解决的所有问题都在启动时注册

static void Main() {
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) => {
services.AddScoped<XtraMain>();
services.AddTransient<FrmExpressionOfNeeds>();
services.AddTransient<Form2>();
services.AddTransient<Form3>();
services.AddSingleton<ISqlDataAccess, SqlDataAccess>();
services.AddSingleton<IExpressionOfNeeds, ExpressionOfNeeds>();
services.AddSingleton<IFormFactory, FormFactory>();
});
var host = builder.Build();
using (var serviceScope = host.Services.CreateScope()) {
IServiceProvider services = serviceScope.ServiceProvider;
XtraMain mainform = services.GetRequiredService<XtraMain>();
Application.Run(mainform);
}
}

这样,无论有多少表单和接口,容器都可以解析和注入所有依赖项。

最新更新