Best practice per l'accesso a WinForm
Ho un accesso funzionante per un progetto WinForms. Uso il program.cs
file per avviare il modulo di accesso. Non sono così sicuro che non ci sia un modo migliore per implementarlo.
Ecco il mio file program.cs:
using System;
using System.Windows.Forms;
using WindowsFormsApp.Presenters;
using WindowsFormsApp.Views;
using Autofac;
using DbContexts;
using Serilog;
namespace WindowsFormsApp
{
internal static class Program
{
public static IContainer Container { get; private set; }
public static string UserName { get; set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
var builder = new ContainerBuilder();
builder.Register(c => new MyContext());
Container = builder.Build();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.RollingFile("log-{Date}.txt")
.CreateLogger();
Log.Information("Application Started");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var loginForm = new LoginForm();
var results = loginForm.ShowDialog();
if (results == DialogResult.Cancel)
System.Environment.Exit(1);
while (results != DialogResult.OK)
{
results = loginForm.ShowDialog();
if (results == DialogResult.Cancel)
System.Environment.Exit(1);
}
var mainFormView = new MainFormView();
mainFormView.Tag = new MainFormPresenter(mainFormView);
Application.Run(mainFormView);
}
}
}
Eventuali suggerimenti o commenti sono i benvenuti.
Risposte
- Hai una proprietà statica pubblica UserName che può essere impostata da chiunque, ovunque nel tuo codice. Non hai specificato l'utilizzo di questa proprietà.
Se è il modulo di accesso che dovrebbe aggiornarlo e non si aggiornerà mai più, chiedi alla classe del programma di impostare questo campo.
Se è un'altra classe che aggiorna questo campo, forse questa proprietà non appartiene a questo.
Hai del codice duplicato, quindi deve esserci un modo per fare meglio.
Dal mio punto di vista, stai facendo molte cose diverse nel tuo metodo Main, forse potresti mettere queste operazioni in metodi separati: Init, Login, Start.
Usa usando
Metti il Presenter per MainForm nella proprietà Tag, che penso appartenga a una proprietà specifica. In questo modo la MainForm può controllare chi vi ha accesso, altrimenti qualsiasi oggetto che ha accesso alla MainForm può recuperare il Tag e quindi il Presenter. Un altro problema è che la proprietà Tag è un oggetto, quindi dovrai convertirla ogni volta che vuoi usarla.
Quindi, tutto insieme che diventerebbe:
using System;
using System.Windows.Forms;
using WindowsFormsApp.Presenters;
using WindowsFormsApp.Views;
using Autofac;
using DbContexts;
using Serilog;
namespace WindowsFormsApp
{
internal static class Program
{
public static IContainer Container { get; private set; }
public static string UserName { get; private set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Init();
Login();
Start();
}
private void Init()
{
var builder = new ContainerBuilder();
builder.Register(c => new MyContext());
Container = builder.Build();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.RollingFile("log-{Date}.txt")
.CreateLogger();
Log.Information("Application Started");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
}
private void Login()
{
using (loginForm = new LoginForm())
{
var results DialogResult.None;
do
{
results = loginForm.ShowDialog();
if (results == DialogResult.Cancel)
System.Environment.Exit(1);
} while (results != DialogResult.OK);
//Since we logged on correctly, we can update UserName (I guess)
UserName = loginForm.ValidatedUserName;
}
}
private void Start()
{
using (var mainFormView = new MainFormView())
{
mainFormView.Presenter = new MainFormPresenter(mainFormView);
Application.Run(mainFormView);
}
}
}
}
La prima cosa che ho notato. Duplicazione del codice. Ogni volta che vedi questo il tuo primo pensiero dovrebbe essere: "Ci deve essere un modo migliore".
In questo caso assegna la variabile result a DialogResult.None
quindi mostra solo la finestra di dialogo all'interno del ciclo:
var result = DialogResult.None;
while(result != DialogResult.OK)
{
result = loginForm.ShowDialog();
if(result == DialogResult.Cancel)
{
System.Environment.Exit(1);
}
}