Este es mi código detrás del formulario ExpressionOfNeeds
private readonly IExpressionOfNeeds _expressionOfNeeds; public FrmExpressionOfNeeds(IExpressionOfNeeds expressionOfNeeds) { InitializeComponent(); _expressionOfNeeds = expressionOfNeeds; } private async void FrmExpressionOfNeeds_Load(object sender, EventArgs e) { GCData.DataSource = await _expressionOfNeeds.GetAllExpressionOfNeeds(); }y este es mi código detrás de MainForm
private readonly IExpressionOfNeeds _expressionOfNeeds; private readonly IService2 _service2; private readonly IService3 _service3; //and so on and so forth public XtraMain() { InitializeComponent(); } private void bbtnExpressionOfNeeds_ItemClick(object sender, ItemClickEventArgs e) { FrmExpressionOfNeeds frme = new(_expressionOfNeeds) { Name = "FrmExpressionOfNeeds" }; ViewChildForm(frme); } private void bbtnForm2_ItemClick(object sender, ItemClickEventArgs e) { Form2 frme = new(_service2) { Name = "Form2" }; ViewChildForm(frme); } private void bbtnForm3_ItemClick(object sender, ItemClickEventArgs e) { Form3 frme = new(_service3) { Name = "Form3" }; ViewChildForm(frme); } y así sucesivamente y así sucesivamente
y este es mi código detrás de la clase Program
static void Main() { var builder = new HostBuilder() .ConfigureServices((hostContext, services) => { services.AddScoped<XtraMain>(); services.AddSingleton<ISqlDataAccess, SqlDataAccess>(); services.AddSingleton<IExpressionOfNeeds, ExpressionOfNeeds>(); }); var host = builder.Build(); using (var serviceScope = host.Services.CreateScope()) { var services = serviceScope.ServiceProvider; var mainform = services.GetRequiredService<XtraMain>(); Application.Run(mainform); } } el problema es que el valor de _expressionOfNeeds siempre es nulo y no puedo encontrar la manera de inicializarlo
Actualizar
Tengo muchos formularios y muchas interfaces.
Solo lo he limitado a un ejemplo para que el código no sea demasiado grande.
Sugeriría crear una fábrica para obtener los formularios que necesita el formulario principal
public interface IFormFactory { TForm Create<TForm>() where TForm : Form; } asumiendo que los tipos que se crearán en este caso derivan de Form
la implementación utilizará el proveedor de servicios para resolver el tipo de formulario proporcionado
public class FormFactory: IFormFactory { private readonly IServiceProvider services; public FormFactory(IServiceProvider services) { this.services = services; } public TForm Create<TForm>() where TForm : Form { return services.GetRequiredService<TForm>(); } }El formulario principal deberá depender de la fábrica para que pueda crear los formularios según sea necesario.
//... private readonly IFormFactory factory; public XtraMain(IFormFactory factory) { InitializeComponent(); this.factory = factory; } private void bbtnExpressionOfNeeds_ItemClick(object sender, ItemClickEventArgs e) { FrmExpressionOfNeeds frme = factory.Create<FrmExpressionOfNeeds>(); frme.Name = "FrmExpressionOfNeeds"; ViewChildForm(frme); } private void bbtnForm2_ItemClick(object sender, ItemClickEventArgs e) { Form2 frme = factory.Create<Form2>(); frme.Name = "Form2"; ViewChildForm(frme); } private void bbtnForm3_ItemClick(object sender, ItemClickEventArgs e) { Form3 frme = factory.Create<Form3>(); frme.Name = "Form3"; ViewChildForm(frme); } //...Asegúrese de que todo lo que debe resolver el proveedor de servicios esté registrado al inicio
static void Main() { var builder = new HostBuilder() .ConfigureServices((hostContext, services) => { services.AddScoped<XtraMain>(); services.AddTransient<FrmExpressionOfNeeds>(); services.AddTransient<Form2>(); services.AddTransient<Form3>(); services.AddSingleton<ISqlDataAccess, SqlDataAccess>(); services.AddSingleton<IExpressionOfNeeds, ExpressionOfNeeds>(); services.AddSingleton<IFormFactory, FormFactory>(); }); var host = builder.Build(); using (var serviceScope = host.Services.CreateScope()) { IServiceProvider services = serviceScope.ServiceProvider; XtraMain mainform = services.GetRequiredService<XtraMain>(); Application.Run(mainform); } }De esa manera, todas las dependencias pueden ser resueltas e inyectadas por el contenedor, independientemente de cuántos formularios e interfaces haya.
Ya casi has llegado. Ha registrado el formulario y los servicios en el contenedor DI, pero olvidó inyectar las interfaces en el constructor de su formulario.
Debe agregar interfaces dependientes al constructor del formulario (solución preferida) u obtener una instancia de ellas del proveedor de servicios más adelante cuando lo necesite.
Puedes encontrar un ejemplo paso a paso en el siguiente post:
Suponiendo que tiene un MainForm que depende de IMyServie , entonces debería tener un constructor como este:
IMyService _myService; public MainForm(IMyService myService) { _myService = myService; } Luego, una vez que registre MainForm e IMyService en el contenedor DI y obtenga la instancia del proveedor de servicios, todo funcionará como se esperaba. Aquí está el punto de entrada principal:
static class Program { public static IServiceProvider ServiceProvider { get; private set; } [STAThread] static void Main() { ApplicationConfiguration.Initialize(); var host = CreateHostBuilder().Build(); ServiceProvider = host.Services; Application.Run(ServiceProvider.GetRequiredService<MainForm>()); } static IHostBuilder CreateHostBuilder() { return Host.CreateDefaultBuilder() .ConfigureServices((context, services)=>{ services.AddTransient<IMyService, MyService>(); services.AddTransient<MainForm>(); }); } } Si por alguna razón (como lo que expliqué en la respuesta vinculada) necesita obtener una instancia de un servicio sin inyectarlo en el constructor, entonces puede usar Program.ServiceProvider.GetRequiredService<SomeFormOrService>() .