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 (Open-Closed Principle) を保存したいので、将来別のプラグイン クラスを追加しても、メイン クラスは変更されません。

これがメインクラス

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には、実装タイプを知る必要があります。Factory Patternを見てください。

于 2012-04-23T14:07:54.820 に答える
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;
}
于 2012-04-23T14:09:59.370 に答える
1

プラグインを保存するコレクションを追加できます。コレクションを 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などを使用することもできます。

于 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
        }
    }


 }
}

SO これはすべてのプラグインを含む名前空間です

今メインアプリで

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 に答える