Как передать параметры конструкторам, неизвестным заранее? - PullRequest
0 голосов
/ 26 января 2012

Эта функция загрузит сборку, позволит пользователю выбрать форму из списка и затем попытаться вызвать ее.В случае успеха, возвращая форму.

Моя проблема заключается в том, как создать экземпляр конструктора с параметрами ожидаемого типа.если конструктор ожидает List<string>, следует указать пустое значение List<String>, а не просто ноль.

Любые идеи?

private Form SelectForm(string fileName)
{
    Assembly assembly = Assembly.LoadFrom(fileName);
    var asmTypes = assembly.GetTypes().Where(F => F.IsSubclassOf(typeof(Form)));
    string SelectedFormName;
    using (FrmSelectForm form = new FrmSelectForm())
    {
        form.DataSource = (from row in asmTypes
                           select new { row.Name, row.Namespace, row.BaseType }).ToList();

        if (form.ShowDialog(this) != DialogResult.OK)
            return null;
        SelectedFormName = form.SelectedForm;
    }

    Type t = asmTypes.Single<Type>(F => F.Name == SelectedFormName);
    foreach (var ctor in t.GetConstructors())
    {
        try
        {
            object[] parameters = new object[ctor.GetParameters().Length];
            for (int i = 0; i < ctor.GetParameters().Length; i++)
            {
                parameters[i] = ctor.GetParameters()[i].DefaultValue;
            }
            return Activator.CreateInstance(t, parameters) as Form;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    return null;
}

Ответы [ 2 ]

1 голос
/ 26 января 2012

Если вы знаете, что такое тип параметра, замените:

parameters[i] = ctor.GetParameters()[i].DefaultValue;

на

parameters[i] = new List<string>();

Если вы не знаете, вам нужно создать экземпляр, используя те же методы отражения:

object p1 = Activator.CreateInstance(parameters[i].ParameterType), 
return Activator.CreateInstance(t, [p1]) as Form;
0 голосов
/ 30 января 2012

для создания объектов из определений типов этот метод работает очень хорошо.

private Form SelectForm(string fileName,string formName)
{
    Assembly assembly = Assembly.LoadFrom(fileName);
    var asmTypes = assembly.GetTypes().Where(F => F.IsSubclassOf(typeof(Form)));

    Type t = asmTypes.Single<Type>(F => F.Name == formName);
    try
    {
        var ctor = t.GetConstructors()[0];
        List<object> parameters = new List<object>();
        foreach (var param in ctor.GetParameters())
        {
            parameters.Add(GetNewObject(param.ParameterType));
        }
        return ctor.Invoke(parameters.ToArray()) as Form;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    return null;
}

...

public static object GetNewObject(Type t)
{
    try
    {
        return t.GetConstructor(new Type[] { }).Invoke(new object[] { });
    }
    catch
    {
        return null;
    }
}
...