.NET 5 Windows 具有依赖注入的表单 - 如何将表单属性从一个表单传递到另一个表单?

.NET 5 Windows Forms with Dependency Injection - How to pass form properties from one form to another?

我正在使用依赖注入 (DI) 将 .NET Framework Windows 表单应用程序升级到 .NET 5。有些表单调用其他表单并将表单属性作为参数传递。因此,CustomerSummary 调用 CustomerDetail 并传入 CustomerId。下面演示了如何从一个表单调用另一个表单:

https://marcominerva.wordpress.com/2020/03/09/using-hostbuilder-serviceprovider-and-dependency-injection-with-windows-forms-on-net-core-3/

但是,它没有显示 MainForm 如何将参数传递给 SecondForm。使用 DI 时如何将参数从一种形式传递到另一种形式?或者,我是否只创建一个 new 表单并在参数列表中传递值以及 ServiceProvider(这似乎违背了 DI 的目的)?代码如下:

CustomerSummary.cs

public partial class CustomerSummary : Form
{
    protected IConfiguration Configuration { get; set; }
    protected SomeDbNameEntities DbContext { get; set; }
    protected IServiceProvider ServiceProvider { get; set; }
    
    public CustomerSummary(IServiceProvider objServiceProvider)
    {
        this.Configuration = (IConfiguration)objServiceProvider.GetService(typeof(IConfiguration));

        this.DbContext = (SomeDbNameEntities)objServiceProvider.GetService(typeof(SomeDbNameEntities));

        this.ServiceProvider = (IServiceProvider)objServiceProvider.GetService(typeof(IServiceProvider));

        InitializeComponent();
        BindCustomerGrid();
    }

    private void dgvCustomer_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        if ((dgvCustomer.SelectedRows[0].Cells[0].Value) != DBNull.Value)
        {
            int CustomerId = (int)dgvCustomer.SelectedRows[0].Cells[0].Value;

            // .NET Framework
            CustomerDetail chForm = new CustomerDetail(CustomerId); 

            // .NET 5. How do I pass the CustomerId?
            Form chForm = (CustomerDetail)ServiceProvider.GetService(typeof(CustomerDetail));

            chForm.Show();
        }
    }   
}   

CustomerDetail.cs

public partial class CustomerDetail : Form
{
    protected IConfiguration Configuration { get; set; }
    protected SomeDbNameEntities DbContext { get; set; }
    protected IServiceProvider ServiceProvider { get; set; }
    int BillToID;
    
    public CustomerDetail(int custid, IServiceProvider objServiceProvider)
    {
        this.Configuration = (IConfiguration)objServiceProvider.GetService(typeof(IConfiguration));

        this.DbContext = (SomeDbNameEntities)objServiceProvider.GetService(typeof(SomeDbNameEntities));

        this.ServiceProvider = (IServiceProvider)objServiceProvider.GetService(typeof(IServiceProvider));

        this.BillToID = custid;
        InitializeComponent();
    }
}

更新 CustomerSummary 表单本身是通过以下调用从另一个表单(称为 MainMenu)调用的:

Form chForm = (CustomerSummary)ServiceProvider.GetService(typeof(CustomerSummary)); 

chForm.Show()

这就是您看到明显的反模式行为的原因。由于您更改了 CustomerSummary 构造函数(我基本上添加了两个以使 MainForm 调用起作用),这将如何改变您的解决方案,因为现在我收到一个与以下事实相关的构建错误调用了错误的构造函数。我需要创建一个 CustomerSummaryFactory 吗?

将 ServiceProvider 用作服务定位器在某种程度上是一种反模式。比如直接把需要的依赖注入到CustomerDetail中比较好。

public CustomerDetail(int custid, IConfiguration configuration, SomeDbNameEntities dbContext)
{
    this.Configuration = configuration;

    this.DbContext = dbContext;

    this.BillToID = custid;
    InitializeComponent();
}

如如何传入custid。一种常见的方法是使用工厂。它可能看起来像这样

public class CustomerDetailFactory
{
    private IServiceProvider serviceProvider;
    
    public CustomerDetailFactory(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }
    
    public CustomerDetail Create(int custid)
    {
        var configuration = (IConfiguration)this.serviceProvider.GetService(typeof(IConfiguration));
        var dbContext = (SomeDbNameEntities)this.serviceProvider.GetService(typeof(SomeDbNameEntities));
        
        return new CustomerDetail(custid, configuration, dbContext);
    }
}

然后在 CustomerSummary 中使用它

public partial class CustomerSummary : Form
{
    private CustomerDetailFactory customerDetailFactory;
    
    public CustomerSummary(CustomerDetailFactory customerDetailFactory)
    {
        this.customerDetailFactory = customerDetailFactory;

        InitializeComponent();
        BindCustomerGrid();
    }

    private void dgvCustomer_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        if ((dgvCustomer.SelectedRows[0].Cells[0].Value) != DBNull.Value)
        {
            int CustomerId = (int)dgvCustomer.SelectedRows[0].Cells[0].Value;

            Form chForm = this.customerDetailFactory.Create(CustomerId);

            chForm.Show();
        }
    }   
}

不要忘记在 Program.cs

中将工厂注册为服务
Services.AddTransient<CustomerDetailFactory>();