【问题标题】:.NET 5 Windows Forms with Dependency Injection - How to pass form properties from one form to another?.NET 5 Windows Forms with Dependency Injection - 如何将表单属性从一个表单传递到另一个表单?
【发布时间】:2021-03-19 17:33:24
【问题描述】:

我正在使用依赖注入 (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吗?

【问题讨论】:

  • 我可能是错的,但我认为 DI 框架不会允许您通过 int 类型进行注入。要使用 DI 执行此操作,我认为您必须创建一个类,然后使用工厂,因为 custid 正在更改:stackoverflow.com/a/37765719/1429439。

标签: c# winforms dependency-injection .net-5


【解决方案1】:

使用 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>();

【讨论】:

  • 感谢您的全面回复。为了尽可能简化问题,我似乎无意中遗漏了一些相关信息。你能评论和建议吗?
  • 您是否将 CustomerDetailFactory 注册为服务?
  • 天啊!我现在做了。我一直忘记添加服务。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
相关资源
最近更新 更多