2012-04-23 4 views
0

私は非常に基本的な質問をしています(私はなぜstrightを考えることができないのか分かりません)。簡単な多型を実現する方法を探している

多形性を試しています。

私はこのようなインターフェイスの外観を持っている:

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

このインタフェースをimplamentいくつかのプラグインクラスは、だから私は、メインクラスを持っていると私はそれがすべてを起動したいですプラグイン

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

実際の質問は何ですか。あなたは確かにそこにいくつかの継承を必要とするdoSomethingバーチャルを作るために? – Ian

+0

プラグインの作成は簡単なプログラミング作業ではありません。多くの標準的なプラクティスに従わない/できないことが多い理由です。プログラミングについて学ぶための例を見つけようとしているのであれば、少なくとも今はプラグインから遠ざかることをお勧めします。これが単なる学問的な運動でないならば、私を無視して自由に感じてください。 – Servy

答えて

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"); 

     } 

    } 
} 

}

と名前空間です
1

メインクラスです。コレクションは1つの場所に塗りつぶしてから、別のメソッドに渡してすべてのプラグインを繰り返し処理して呼び出すことができます。この方法では、コレクション内のどのタイプのプラグインにも完全に依存しません。

@と述べたように、これは正しく動作するようにdoSomthingvirtualと宣言する必要があります。

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); 
    } 
    } 
} 

これは(まあ、それは本当のDIにするために、あなたは別のクラスにfuncを入れなければならない)多型の1よく知られたアプリケーションである、Dependency Injectionの単純化した例です。コードの柔軟性を高め、プラグインの作成とその使用方法を切り離すために、たとえば、 a Factory MethodまたはBuilderである。

2

もちろん、特定のIpluginを作成するには、実装タイプを知る必要があります。 Factory Patternを見てください。

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; 
} 
+0

HI、PluginAttributeが必要なのは何ですか?私はそれに何を入れなければならないのですか? – MoShe

+0

@MoShe私は工場のクラスをマークするために属性を使用します。そのようにして、工場は、ロードされたすべてのアセンブリの各クラスをチェックし、IPluginインターフェイスを実装し、その属性を持っているかどうかを確認する必要があります。抽象プラグインはインターフェイスのみを持つかもしれませんが、属性を持つべきではありません。両方が真の場合、属性の名前と型はディクショナリに格納されます。もちろん、登録メソッドを作成し、PéterTöröksのような手でそれを行うこともできます。しかし、私はこの自動方法を好む。 – dowhilefor

+0

私の答えはどう思いますか?私はそれがocpを保存すると思う – MoShe

関連する問題