Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体?_C#_Winforms_Dependency Injection_.net 5 - Fatal编程技术网

C# 带有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体?

C# 带有依赖项注入的.NET 5 Windows窗体-如何将窗体属性从一个窗体传递到另一个窗体?,c#,winforms,dependency-injection,.net-5,C#,Winforms,Dependency Injection,.net 5,我正在使用依赖项注入(DI)将.NET Framework Windows窗体应用程序升级到.NET 5。有些表单调用其他表单并将表单属性作为参数传入。因此,CustomerSummary调用CustomerDetail并传入一个CustomerId。下面演示了如何从一个表单调用另一个表单: 但是,它没有显示MainForm如何将参数传递给SecondForm。在使用DI时,如何将参数从一种形式传递到另一种形式?或者,我只是创建一个新的表单,并将值连同服务提供者一起传递到参数列表中(这似乎不符

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

但是,它没有显示
MainForm
如何将参数传递给
SecondForm
。在使用DI时,如何将参数从一种形式传递到另一种形式?或者,我只是创建一个
新的
表单,并将值连同
服务提供者
一起传递到参数列表中(这似乎不符合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();
        }
    }   
}   
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();
    }
}
Services.AddTransient<CustomerDetailFactory>();
CustomerDetail.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();
        }
    }   
}   
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();
    }
}
Services.AddTransient<CustomerDetailFactory>();
更新
CustomerSummary
表单本身通过以下调用从另一个表单(称为
main menu
)调用:

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();
}
至于如何传递客户ID。一种常见的方法是使用工厂。它可能看起来像这样

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中将工厂注册为服务

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();
        }
    }   
}   
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();
    }
}
Services.AddTransient<CustomerDetailFactory>();
Services.AddTransient();

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

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

    this.DbContext = dbContext;

    this.BillToID = custid;
    InitializeComponent();
}
至于如何传递客户ID。一种常见的方法是使用工厂。它可能看起来像这样

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中将工厂注册为服务

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();
        }
    }   
}   
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();
    }
}
Services.AddTransient<CustomerDetailFactory>();
Services.AddTransient();

我可能错了,但我认为DI框架不会允许您按int类型进行注入。要使用DI实现这一点,我认为您必须创建一个类,然后使用工厂,因为custid正在更改:。我可能错了,但我认为DI框架不允许您按int类型进行注入。要使用DI实现这一点,我认为您必须创建一个类,然后使用工厂,因为custid正在更改:。感谢您的全面回复。看来我无意中遗漏了一些相关信息,试图尽可能简化这个问题。你能回顾一下并提出建议吗?你是否将CustomerDetailFactory注册为一项服务?哦!我现在知道了。我总是忘记添加服务。谢谢在此补充问题,感谢您的全面回复。看来我无意中遗漏了一些相关信息,试图尽可能简化这个问题。你能回顾一下并提出建议吗?你是否将CustomerDetailFactory注册为一项服务?哦!我现在知道了。我总是忘记添加服务。谢谢在此添加问题