Question

This function will load an assembly, let the user select a form from a list, and then try to invoke it. If successful, returning the form.

My problem is how to instantiate the constructor with parameters that is of the expected type. if the constructor expect List<string> an empty List<String> should be supplied, not just null.

Any Ideas?

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;
}
Was it helpful?

Solution 2

in order to create objects from types definitions this method works very well.

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;
    }
}

OTHER TIPS

If you know what is a parameter type, replace:

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

to

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

If you don't know, you need create instance using same reflection methods:

object p1 = Activator.CreateInstance(parameters[i].ParameterType), 
return Activator.CreateInstance(t, [p1]) as Form;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top