0

我有一个非常基本的问题(我不知道为什么我无法思考)。

我正在尝试做一些多态性。

我的界面如下所示:

Public interface Iplugin
{

   void doSomthing(string _str);
}

我也有一些实现这个接口的插件类

public class plugin1:Iplugin
{
    void doSomthing(string _str)
    {
        if (_str=="1")
        {
           // do somthing 1
        }
     }
 }

 public class plugin2:Iplugin
{
    void doSomthing(string _str)
    {
        if (_str=="2")
        {
           // do somthing 2
        }
     }
 }

public class plugin3:Iplugin
{
    void doSomthing(string _str)
    {
        if (_str=="3")
        {
           // do somthing 3
        }
     }
 }

所以我有主类,我希望它调用所有插件

但我希望它保存 OCP(开闭原则),所以如果我将来添加另一个插件类,主类不会改变。

这是主要课程

public class mainApp
{
  Iplugin _context;
  mainApp()
  {
     _context= new //new what??
  }
  bool func(string str)
  {
      _context.doSomthing(str);//I would like it to invoke all the plug in and also a future plugins that I will add
  }
} 
4

4 回答 4

2

当然,要创建一个特定的Iplugin你需要知道实现类型。看看工厂模式

于 2012-04-23T14:07:54.820 回答
2

对于这种情况,我喜欢使用工厂模式。您可以轻松地将其与一些属性和反射魔法结合起来,构建可用插件的存储库

[PluginAttribute("myPlugin")]
class MyPlugin : IPlugin

现在工厂最初检查所有加载的程序集中的所有类并搜索属性并将类型和插件字符串标识符存储在字典中。

class PluginFactory
{
    static Iplugin CreatePlugin(string aName)
    {
        return Activator.CreateInstance( sRegisteredPlugins[aName]);
    }

    private static Dictionary<string, Type> sRegisteredPlugins;
}
于 2012-04-23T14:09:59.370 回答
1

您可以添加一个集合来存储您的插件。集合可以在一个地方填充,然后传递给另一个方法,该方法只是遍历所有插件并调用它们。这样,它完全独立于集合中的插件类型。

正如@Ian 提到的,您需要声明doSomthing virtual它才能正常工作。

public class mainApp
{
  mainApp()
  {
    List<Iplugin> plugins = new ArrayList<Iplugin>;

    ...

    plugins.add(new plugin1());
    ...
    plugins.add(new plugin3());
    ...
    func(plugins, "1");
    ...
    func(plugins, "7");
  }

  bool func(List<IPlugin> plugins, string str)
  {
    foreach (IPlugin plugin in plugins) {
      plugin.doSomthing(str);
    }
  }
}

这是Dependency Injection的一个简单示例,它是多态性的一个众所周知的应用(好吧,要使其成为真正的 DI,您应该放入func不同的类)。为了使您的代码更加灵活,并将插件的创建与它们的使用分离,您还可以使用例如工厂方法构建器

于 2012-04-23T14:06:52.513 回答
0

好的,谢谢大家的帮助。

我接受了您的所有建议,并做了以下事情:

 namespace Plugins
{




 public class plugin1 : Iplugin
  {
    void doSomthing(string _str)
    {
        if (_str == "1")
        {
            // do somthing 1
        }
    }


}

public class plugin2 : Iplugin
{
    void doSomthing(string _str)
    {
        if (_str == "2")
        {
            // do somthing 2
        }
    }


}

public class plugin3 : Iplugin
{
    void doSomthing(string _str)
    {
        if (_str == "3")
        {
            // do somthing 3
        }
    }


 }
}

所以这是包含所有插件的名称空间

现在在主应用程序中

namespace Factory
{
  public interface Iplugin
  {

    void doSomthing(string _str);
  }



class Program
{
    static void Main(string[] args)
    {
        string @namespace = "Plugins";

        var q = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.IsClass && t.Namespace == @namespace
                select t;
        q.ToList();

        List<Iplugin> myList = new List<Iplugin>();
        foreach (var item in q)
        {
            Iplugin temp=(Iplugin)Activator.CreateInstance(item);
            myList.Add(temp);// a list with all my plugins

        }

        foreach (var item in myList)
        {
           item.doSomthing("string");

        }

    }
}

}

于 2012-04-23T19:29:50.813 回答