Práticas recomendadas de logon do WinForm

Aug 17 2020

Eu tenho um logon de trabalho para um projeto WinForms. Eu uso o program.csarquivo para iniciar o formulário de login. Não tenho tanta certeza de que não haja uma maneira melhor de implementar isso.

Aqui está o meu arquivo 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);
            }
        }
    }

Quaisquer sugestões ou comentários são bem-vindos.

Respostas

4 MartinVerjans Aug 17 2020 at 16:18
  1. Você tem uma propriedade estática pública UserName que pode ser definida por qualquer pessoa, em qualquer lugar do seu código. Você não detalhou o uso desta propriedade.
  • Se for o formulário de logon que deve atualizá-lo e ele nunca mais será atualizado, faça com que sua classe Program defina esse campo.

  • Se for outra classe que atualiza este campo, talvez esta propriedade não pertença aqui.

  1. Você tem algum código duplicado, então deve haver uma maneira de fazer melhor.

  2. Do meu ponto de vista, você está fazendo muitas coisas diferentes em seu método Main, talvez você possa colocar essas operações em métodos separados: Init, Login, Start.

  3. usar usando

  4. Você coloca o Presenter para MainForm na Tag Property, que eu acho que pertence a uma propriedade específica. Dessa forma o MainForm pode controlar quem tem acesso a ele, caso contrário qualquer objeto que tenha acesso ao MainForm pode recuperar o Tag e consequentemente o Presenter. Outro problema é que a propriedade Tag é um objeto, então você terá que convertê-la toda vez que quiser utilizá-la.

Assim, todos juntos se tornariam:

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);
            }
        }
    }
}
2 tinstaafl Aug 17 2020 at 06:45

A primeira coisa que notei. Duplicação de código. Sempre que você vir isso, seu primeiro pensamento deve ser: "Tem que haver uma maneira melhor".

Neste caso, atribua a variável de resultado para DialogResult.Nonemostrar apenas a caixa de diálogo dentro do loop:

var result = DialogResult.None;
while(result != DialogResult.OK)
{
    result = loginForm.ShowDialog();
    if(result == DialogResult.Cancel)
    {
        System.Environment.Exit(1);
    }
}