2012-01-26 41 views
-1

该函数将加载一个程序集,让用户从列表中选择一个表单,然后尝试调用它。如果成功,则返回表单。如何向构造函数提供参数,事先不知道?

我的问题是如何实例化具有预期类型的​​参数的构造函数。 如果构造函数期望List<string>应该提供一个空的List<String>,而不仅仅是null。

什么想法?

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

如果它所希望的'IList'? – dasblinkenlight

+0

你想达到什么目的?假设构造函数需要一个非空的列表,你应该添加到列表中以使其工作吗?或者你是否知道所有的ctors只有基元,可以为空但不为空的集合,或者具有这种构造器的对象实例?在这种情况下,它可能会运行 –

+0

boiut让用户选择值 - 没有办法计算出什么_sensible_值使用。例如。一个空列表可能会被调用 –

回答

0

为了创建从t ypes定义这个方法工作得很好。

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

如果你知道什么是参数类型,替代:

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

恩,那正是我所要求的,如何创建这些参数。当我使用DafaultValue时,一个字符串列表将变为空,这对构造函数来说不是一个有效的参数。 – Stig

+0

@Stig Hm ...我给你写了你应该做的事情。问题是:你知道什么样的参数类型,或者它可以是动态的,你不知道什么类型的参数是?对于dynamic:object p1 = Activator.CreateInstance(typeof(parameters [i])),则:返回Activator.CreateInstance(t,[p1])作为Form; –

+0

现在你更接近解决方案,但它不适用于接口... – Stig