看看如何实现简单的多态性

时间:2012-04-23 14:03:40

标签: c# interface polymorphism implementation open-closed-principle

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

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

我的界面看起来像这样:

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 个答案:

答案 0 :(得分:2)

当然,要创建特定的Iplugin,您需要了解实现类型。查看Factory Pattern

答案 1 :(得分:2)

对于这样的情况,我喜欢使用Factory Pattern。您可以轻松地将其与某些属性和反射魔法相结合,以构建可用插件的存储库

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

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

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

    private static Dictionary<string, Type> sRegisteredPlugins;
}

答案 2 :(得分: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放到另一个类中)。为了使您的代码更加灵活,并将插件的创建与其使用分离,您还可以使用例如Factory MethodBuilder

答案 3 :(得分: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");

        }

    }
}

}