【问题标题】:How can I dynamically call a method using Namespace.Class in C#?如何在 C# 中使用 Namespace.Class 动态调用方法?
【发布时间】:2010-12-12 08:04:29
【问题描述】:

我有这样的活动:

private void btnStartAnalysis_Click(object sender, EventArgs e)
{
    SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
    objConnectionString.DataSource = txtHost.Text;
    objConnectionString.UserID = txtUsername.Text;
    objConnectionString.Password = txtPassword.Text;
    objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
    string[] arrArgs = { objConnectionString.ConnectionString };

    //Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.
    string assemblyName = cmbOperations.SelectedValue.ToString();
    Assembly assembly = Assembly.LoadFrom(assemblyName);
    Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");

    IMFDBAnalyserPlugin analyser = (IMFDBAnalyserPlugin) Activator.CreateInstance(localType);
    string response = analyser.RunAnalysis(objConnectionString.ConnectionString);

    //show the response of the the function call
    txtPluginResponse.Text = response;
}

我希望这条线是动态的:

Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");

其中 PrimaryKeyChecker 是一个命名空间,另一个 PrimaryKeyChecker 是类。

但是我想创建其他命名空间和类,那么有没有办法像这样动态调用它们并将它们加载到组合框中。

public void SetOperationDropDown()
{
    cmbOperations.DataSource = PluginManager.GetAllPlugins();

    if(cmbOperations.Items.Count > 0)
    {
        cmbOperations.SelectedItem = cmbOperations.Items[0];
    }
}

【问题讨论】:

    标签: c# .net winforms methods


    【解决方案1】:

    您几乎已经回答了自己的问题!假设您有一个插件列表,在配置文件或其他文件中进行了配置,那么您的 PluginManager 可以使用类似于以下代码的代码从程序集中加载类型:

    Type analyserType = typeof(IMFDBAnalyserPlugin);
    foreach(Type t in assembly.GetTypes()) {
        if(t.IsSubtypeOf(analyserType) {
            plugins.Add((IMFDBAnalyserPlugin) Activator.CreateInstance(t));
        }
    }
    

    如果您没有插件列表,那么您可以扫描目录并执行与上述相同的操作。您还可以考虑使用像 MEF 这样的插件框架架构,它会为您完成很多工作,并在运行时发现程序集和插件。

    【讨论】:

      【解决方案2】:

      我认为 Tom 的回答可以帮助您填充插件列表。将它们绑定到您将文本/描述放置到类型名称的组合框,并将组合项的值绑定到实际的类型声明。你要求事件是“动态的”......你可能是指通用的吗?然后我建议将 click_event 中的代码重构为私有方法,以便也能够从其他“地方”调用它。然后在 click_event 中,您从当前选定的项目中检索选定的插件类型,并在对 RunAnalysis 的通用函数调用中提供这个,如下所示:

      private void btnStartAnalysis_Click(object sender, EventArgs e)
      {
          if(cmbOperations.SelectedItem != null)
              RunAnalysis<cmbOperations.SelectedItem.Value>();  
      }
      
          private void RunAnalysis<T>()
          {
                  //Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.  
                  //string assemblyName = cmbOperations.SelectedValue.ToString();  
                  //Assembly assembly = Assembly.LoadFrom(assemblyName);  
      
                  //Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");  
      
                      IMFDBAnalyserPlugin analyser = 
                        (IMFDBAnalyserPlugin) Activator.CreateInstance(T);  
      
      string response = analyser.RunAnalysis(objConnectionString.ConnectionString);  
      
                      //show the response of the the function call  
                  txtPluginResponse.Text = response;  
              }
      

      另一种方法可能是只为当前选择的类型使用一个参数。希望这对您有所帮助或为您带来解决方案的新想法。

      【讨论】:

      • 更正代码; Activator.CreateInstance(T) 应该是 Activator.CreateInstance() 并且如果您对方法设置了约束(其中 T : IMFDBAnalyserPlugin),则不需要在 CreateInstance 之后进行强制转换。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多