具有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体? [英] .NET 5 Windows Forms with Dependency Injection - How to pass form properties from one form to another?

查看:67
本文介绍了具有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am upgrading a .NET Framework Windows Form Application to .NET 5 using Dependency Injection (DI). There are forms that call other forms and pass in form properties as parameters. So, CustomerSummary calls CustomerDetail and passes in a CustomerId. The following demonstrated how to call one form from another:

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的目的)?代码如下:

But, it doesn't show how MainForm can pass a parameter to SecondForm. How can I pass a parameter from one form to another when using DI? Or, do I just create a new form and pass the values, along with the ServiceProvider, in the parameter list (this seems to defeat the purpose of DI)? The code is as follows:

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 )调用的:

UPDATE The CustomerSummary form itself is called from another form (called MainMenu) with the following call:

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

chForm.Show()

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

This is why you see apparent anti-pattern behavior. Since you changed the CustomerSummary constructor (I basically added two in order to get the MainForm call to work), how would that change your solution because right now I get a build error relating to the fact that the wrong constructors are being called. Do I need to create a CustomerSummaryFactory?

推荐答案

将ServiceProvider用作服务定位器在某种程度上是一种反模式.例如,最好将所需的依赖项直接注入到CustomerDetail中.

The using of the ServiceProvider as a service locator is somewhat an anti-pattern. For example it's better to directly inject the needed dependencies into CustomerDetail.

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

    this.DbContext = dbContext;

    this.BillToID = custid;
    InitializeComponent();
}

关于如何传递监护权.常见的方法是使用工厂.可能看起来像这样

As how to pass in custid. A common approach is the use of factories. It could look something like this

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中使用它

Then you use it in 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>();

这篇关于具有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆