提问人:October Sith 提问时间:7/4/2022 最后编辑:October Sith 更新时间:7/5/2022 访问量:183
依赖项注入的类返回 Null(c#,Winforms 应用)
Dependency Injected Class Returns Null (c#,Winforms App)
问:
我不确定这里有什么问题,所以我正在联系。我有一个接口化的 DataLayer 类,它调用了我用来填充网格视图的一些客户数据。我将其直接注入到一个 winform 分部类中(我现在跳过 BusinessLayer)。我是 Winforms 的新手,所以也许我在这里没有看到一些东西,或者我的代码很密集。
接口:
namespace DL
{
public interface IRepo<T>
{
List<T> GetAll();
}
}
数据层
namespace DL
{
public class CustomersRepo : IRepo<Customers>
{
string constring = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
public List<Customers> GetAll()
{
List<Customers> customers = new List<Customers>();
string sqlQuery =@"SELECT * FROM CUSTOMERS";
using (SqlConnection con = new SqlConnection(constring))
{
con.Open();
SqlCommand command = new SqlCommand(sqlQuery, con);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Customers customer = new Customers();
customer.CustomerID = reader.GetInt32(0);
customer.LastName = reader.GetString(1);
customer.FirstName = reader.GetString(2);
customer.Address = reader.GetString(3);
customer.City = reader.GetString(4);
customers.Add(customer);
}
}
return customers;
}
}
}
依赖注入:
public partial class Main : Form
{
public List<Customers> CustomersData { get; set; }
private IRepo<Customers> _repo;
public Main(IRepo<Customers> repo)
{
_repo = repo;
}
主要:
public Main()
{
CustomersData = _repo.GetAll();
InitializeComponent();
}
表单负载:
private void Main_Load(object sender, EventArgs e)
{
dataGridViewCust.DataSource = CustomersData;
}
如果我将此 Datalayer 方法直接插入到表单类中,则一切正常。我试图保持我在最近的训练营中学到的一些设计原则,因此试图通过依赖注入来分离关注点。我在某个地方傻了吗?我在这里查看了类似空问题的其他示例,但没有找到我的问题所在......任何帮助或建议将不胜感激。我觉得我在很大程度上忽略了一些东西。
编辑: (我也尝试在没有 IRepo 抽象的情况下直接插入 repo 类。
答:
应在程序 .cs 中执行依赖项注入。为此,请安装 autofac 软件包并编写以下示例代码。
using Autofac;
using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(Container.Resolve< IRepo>()));
}
static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<CustomersRepo>().As<IRepo>();
builder.RegisterType<Form1>();
return builder.Build();
}
}
}
评论
关于设置依赖注入,SO上有几个很好的答案(例如,在C#中的WinForms上使用Microsoft扩展依赖注入)。在您发布的代码中,还有一些其他问题需要解决,但首先应用该链接中的示例以用于创建和配置 .Microsoft.Extensions.DependencyInjection
IServiceProvider
static class Program
{
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Set up DI here
ConfigureServices();
Application.Run(new Main());
}
public static IServiceProvider ServiceProvider { get; set; }
static void ConfigureServices()
{
var services = new ServiceCollection();
services.AddTransient<IRepo<Customer>, CustomersRepo>();
ServiceProvider = services.BuildServiceProvider();
}
}
Main 构造函数
没有必要将接口传递给 ctor,因为现在应该获取服务。Main
Program.ServiceProvider
public Main()
{
InitializeComponent();
_repo =
(IRepo<Customer>)
Program.ServiceProvider.GetService(typeof(IRepo<Customer>));
}
private IRepo<Customer> _repo;
初始化 DataGridView
接下来,我们将设置一个模拟数据库查询进行初始化,如下所示:dataGridViewCust
由于需要响应后续查询,因此它需要一个在客户列表发生更改时通知它。在此示例中,我已将其更改为表单事件的覆盖并对其进行初始化。DataGridView
DataSource
List<Customer>
BindingList<Customer>
Load
Main
/// <summary>
/// A binding list will notify DGV when data changes
/// </summary>
public BindingList<Customer> Customers { get; } = new BindingList<Customer>();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dataGridViewCust.DataSource = Customers;
// Here we're calling a method that simulates the
// sql query by returning a fake list of customers
foreach (var customer in _repo.GetAllMock())
{
Customers.Add(customer);
}
foreach (DataGridViewColumn column in dataGridViewCust.Columns)
{
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
}
使用 BindingList
您可能注意到 被声明为只读属性。执行新查询时,只需在添加新记录之前对其执行 a 即可。BindingList
Clear
private void changeTheBindingListExample()
{
Customers.Clear();
foreach (
var customer in
_repo.NewQueryMock("SELECT * FROM CUSTOMERS WHERE FirstName='Other'"))
{
Customers.Add(customer);
}
}
评论