C#制作app支持插件,运行多个实例,可能吗?

时间:2011-10-26 23:27:02

标签: c# plugins

基本上我需要的是能够为我的应用程序添加新功能,而无需更新应用程序本身。

假设我有一个带有两个插件的应用程序。

应用程序有一个名为 generateNumber();

的函数

Plugin_1 会有以下代码:

void init(){ }

int exec(){
  int number = HOST_APPLICATION.generateNumber();
  number = number * 2;
  return number;
}

Plugin_2 具有相同的结构,只有不同的功能:

void init(){ }

int exec(){
  int number = HOST_APPLICATION.generateNumber();
  number = (number * 10) + 13;
  return number;
}

我需要每个'插件'的多个实例同时运行(每个实例都在自己的线程中),因此同时共有20个线程。代码将是这样的:

主要应用程序:

void init_plugins() { }

void execute_plugins(){
   for(int i=0; i<plugins.count; i++){

      for(int z=0; z<10; z++){
          Thread t = new Thread(plugin_research);
          t.start(plugins[i]);
      }

   }
}

void plugin_research(PluginStructure Plugin){
    Plugin.init();
    int return_val = Plugin.exec();
    // do something with return_val
}

我还需要主机应用程序来调用插件的功能(所有插件的结构都相同)和插件才能调用主机应用程序的功能。

每个插件都有不同的配置控件。我需要在一个地方显示配置,但同时多次调用插件的函数(使用线程)

这可能吗?实现这一目标的最佳方法是什么?我可以用iPlugin做到这一点吗?

4 个答案:

答案 0 :(得分:4)

查看MEF,即http://mef.codeplex.com/的托管扩展性框架。它有很多内置支持插件组件的运行时发现。

答案 1 :(得分:3)

基本上,每个插件都应该从暴露所需方法的基类派生。

public abstract class BasePlugin
{
    protected int number;

    public abstract void init_plugin();
    public abstract int exec(int number);
    public BasePlugin(int number)
    {
        this.number = number;
    }
}

然后你有

public class Plugin1: BasePlugin
{
    public override void init_plugin()
    {
    }

    public override int exec(int number)
    {
    }
}

在您的应用中,您可以创建插件并将其保存在列表中

List<BasePlugin> list = new List<BasePlugin>();
list.Add(new Plugin1(generateNumber()));
BasePlugin p2 = new Plugin2(generateNumber());
p2.init_plugin();
list.Add(p2);
无论你喜欢什么,都可以使用加载的插件 或者(从我编辑的问题中看到)你可以为每个插件创建线程......

要加载插件,您可以使用以下功能:

public static List<T> GetFilePlugins<T>(string filename)
{
    List<T> ret = new List<T>();
    if (File.Exists(filename))
    {
        Type typeT = typeof(T);
        Assembly ass = Assembly.LoadFrom(filename);
        foreach (Type type in ass.GetTypes())
        {
            if (!type.IsClass || type.IsNotPublic) continue;
            if (typeT.IsAssignableFrom(type))
            {
                T plugin = (T)Activator.CreateInstance(type);
                ret.Add(plugin);
            }
        }
    }
    return ret;
}
public static List<T> GetDirectoryPlugins<T>(string dirname)
{
    List<T> ret = new List<T>();
    string[] dlls = Directory.GetFiles(dirname, "*.dll");
    foreach (string dll in dlls)
    {
        List<T> dll_plugins = GetFilePlugins<T>(Path.GetFullPath(dll));
        ret.AddRange(dll_plugins);
    }
    return ret;
}

答案 2 :(得分:3)

查看MEF - http://msdn.microsoft.com/en-us/library/dd460648.aspx。即使您决定不使用它,您也可以看到如何实现和使用这种架构。

答案 3 :(得分:2)

了解托管扩展性框架MEF