Как я могу передать параметры в форму с помощью этого общего метода? - PullRequest
0 голосов
/ 23 мая 2018

У меня есть этот универсальный метод для открытия форм на панели, этот метод наследует от Form, в настоящее время с ограничением, что у него есть пустой конструктор (where T : Form, new())

public void OpenForms<T>() where T : Form, new()
{
    Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
    if (form !=null)
    {
        //If the instance is minimized we leave it in its normal state
        if (form.WindowState == FormWindowState.Minimized)
        {
            form.WindowState = FormWindowState.Normal;
        }
        //If the instance exists, I put it in the foreground
        form.BringToFront();
        return;
    }
    //The form opens
    form = new T();
    form.TopLevel = false;
    container_panel.Controls.Add(form);
    container_panel.Tag = form;
    form.Show();
}

Таким образом, чтобы вызватьit:

OpenForms<Form1>();

Как я могу адаптировать эту функцию для передачи параметров в форму?

В этом случае мне нужно передать два параметра в форму, что-тонапример:

OpenForms<Form1>(param1, param2);

Не все формы получают параметры, но в будущем вам может понадобиться использовать 1/2/3 параметров в зависимости от формы.

Параметрыможет различаться по типу: bool, string, int ...

Что это может получить что-то вроде этого:

public void OpenForms<T>(params object[] args) where T : Form, new() { ... }

Идея состоит в том, чтобы использовать его следующим образом:

object[] args = new object[] { "a", true };

OpenForms<Form1>(args);
OpenForms<Form1>("a", 2, false);
OpenForms<Form1>();

Когда вы получаете параметры, вы можете использовать их при создании формы.

Любая идея, как я могу достичьthis?

Редактировать:

Полагаю, эти два примера форм

public partial class Form1 : Form
{
    public Form1(string param1, bool param2)
    {
        InitializeComponent();
    }

    //......
}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    //......
}

При попыткеЧтобы сделать вызов следующим образом:

OpenForms<Form1>("a" false); //Error
OpenForms<Form2>();

Ошибка:

должен быть неабстрактного типа с открытым конструктором без параметров, чтобы использовать его в качестве параметра 'T'в универсальном типе или методе 'AbrirFormulario (params object [])'

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

Альтернативным решением является создание Interface для создания метода, который позволяет получать параметры.

Это пример:

public interface IForms
{
    void InitializeParameters(params object[] args);
}

Здесь мы определяем метод InitializeParameters, который должен соответствовать формам, реализующим этот интерфейс.

Позже, вформы, которые должны вызываться из универсальной формы, мы добавляем интерфейс в ее определение и обязательный метод:

public partial class Form1 : Form, IForms
{
    public Form1()
    {
        InitializeComponent();
    }

    public void InitializeParameters(params object[] args)
    {
        if (args.Length==2)
        {
            string param1 = args[0].ToString();
            int param2 = (int)args[1];
        }
        else
        {
            throw new Exception("The number of parameters is incorrect");
        }

    }       
}

Теперь мы определим универсальный метод для открытия форм следующим образом:

private void OpenForms<T>(params object[] args) where T : Form,IForms,  new()
{
    Form form;
    form= new T();
    ((IForms)form).InitializeParameters(args);
    form.Show();
}

Наконец, способ его использования будет следующим:

OpenForms<Form1>("a", 2);
OpenForms<Form2>("a", 2, "b");
OpenForms<Form3>();

Следует принять во внимание, что, поскольку метод InitializeParameters был определен, примеры 2 и3 выдаст исключение для неверного количества параметров .С помощью этой формы каждый случай должен контролироваться.

Спасибо пользователю @ Pikoh за вашу помощь.

0 голосов
/ 24 мая 2018

Вот еще альтернативный подход, который не требует Form для реализации интерфейса или действительно заботится о том, как он построен.

Допустим, у нас есть Form, просто для целей тестирования:

public class Form3 : Form
{
    public Form3(bool someParameter, string someTitle)
    {

    }
}

Теперь есть несколько полезных функций самодокументирования конструктора, а именно, что параметры имеют имена.Используя что-то вроде этого:

public void OpenForms<T>(params object[] args) where T : Form
{
    //...
}

Не дает вызывающей стороне никакой информации о том, что такое "аргументы", в каком порядке они принадлежат или что они значат.Поэтому, когда вы называете это так:

OpenForms<Form3>(true, "Some Value");

Intellisense не поможет вам, потому что он просто показывает, что вам нужно передать некоторые (или нет) параметры в метод.Вместо этого лучший способ сделать это - использовать фабрику Func<T> для создания формы:

public void OpenForms<T>(Func<T> factoryMethod) where T : Form
{
    Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
    if (form != null)
    {
        //If the instance is minimized we leave it in its normal state
        if (form.WindowState == FormWindowState.Minimized)
        {
            form.WindowState = FormWindowState.Normal;
        }
        //If the instance exists, I put it in the foreground
        form.BringToFront();
        return;
    }
    form = factoryMethod();
    form.TopLevel = false;
    container_panel.Controls.Add(form);
    container_panel.Tag = form;
    form.Show();
}

, которая затем называется так (обратите внимание, как вы можете также пропустить часть <Form3>Вызов OpenForms, это вывод!):

OpenForms(() => new Form3(true, "Title"));

Со всеми полезными сведениями, которые сопровождают его:

enter image description here

Так что теперь у вас есть самодокументируемый код, не имеет значения, как построена форма, и вы не форсируете интерфейс, который не имеет реальной документации (в коде) о том, к каким параметрам относятся.

0 голосов
/ 23 мая 2018

Чтобы сделать это, вам нужно удалить ограничение new(), чтобы разрешить формы без конструкторов без параметров:

public void OpenForms<T>(params object[] args) where T : Form

Теперь, чтобы создать экземпляр, вам нужно использовать Activator.CreateInstance:

T form = default(T);

if (args == null || args.Length == 0)
    form = Activator.CreateInstance<T>();
else
    form = (T)Activator.CreateInstance(typeof(T), args);

Редактировать: полное решение

public void OpenForms<T>(params object[] args) where T : Form
{
    Form form = container_panel.Controls.OfType<T>().FirstOrDefault();
    if (form !=null)
    {
        //If the instance is minimized we leave it in its normal state
        if (form.WindowState == FormWindowState.Minimized)
        {
            form.WindowState = FormWindowState.Normal;
        }
        //If the instance exists, I put it in the foreground
        form.BringToFront();
        return;
    }
    if (args == null || args.Length == 0)
        form = Activator.CreateInstance<T>();
    else
        form = (T)Activator.CreateInstance(typeof(T), args);
    form.TopLevel = false;
    container_panel.Controls.Add(form);
    container_panel.Tag = form;
    form.Show();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...