具有依赖项注入的.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
.以下内容演示了如何从另一种形式调用一种形式:
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:
但是,它没有显示 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屋!