2012-03-22 5 views
0

これは完全なアーキテクチャ変更がなければ不可能かもしれないが、実行時にユーザーに設定可能なオプションを公開するクラス(プラグイン)があると思う。クラスのインスタンス化後に実行時に依存性注入を使用する

プログラムが起動し、ユーザーはさまざまなプラグインの使用を選択できます。ユーザーはプラグインごとに変更できるオプションがあります。ユーザーは再生ボタンを押します。

ユーザーが使用するプラグインを選択すると、そのクラスのインスタンスが作成され、そのプラグインで使用可能なオプションが表示されます。明らかに通常の状況では、クラスがインスタンス化されたコンストラクタ引数が渡されます。このシナリオでは、プラグインにILoggerのコンストラクタ引数があり、具体クラスにDirectoryPathのコンストラクタ引数がありますが、私のIOCコンテナにそれを渡す?

public class MyPlugin 
{ 
    private ILogger Logger; 
    private Dictionary<string, object> Properties = new Dictionary<string, object>(); 

    public MyPlugin(ILogger Logger) 
    { 
    this.Logger = Logger; 
    SetupProperties(); 
    } 

    private SetupProperties() 
    { 
    Properties.Add("LogDirectory","Please enter a directory"); 
    } 

    private void UserPressedPlay() 
    { 
    //We can now read the property values user has entered 
    //Now I want to instantiate FileLogger with the LogDirectory property 
    } 

    public DoSomething(string Data) 
    { 
    this.Logger.Write(Data); 
    } 
} 

public interface ILogger 
{ 
    void Write(string Data); 
} 

public FileLogger : ILogger 
{ 
    private string DirectoryPath; 

    public FileLogger(string Directory) 
    { 
    this.DirectoryPath = Directory; 
    } 

    public Write(string Data) 
    { 
     //Write to file 
    } 
} 
+3

私は現在IOCコンテナを使用していないので、これを回答として投稿しませんが、実際のILoggerではなくILoggerファクトリを渡すことをお勧めします。ファクトリは、ユーザの引数でUsrePressedPlayから呼び出され、実際のLoggerインスタンスを作成できます。 –

+0

現在のアーキテクチャを変更することなく、IoCのデフォルトのコンストラクタ設定をAppData \ Local \ Tempフォルダに設定し、ユーザーがクリックした後にLoggerインターフェイスを再初期化します。 これはややこしいことですが、ロガーの工場の言及を500回伝えるのは間違いですが、Internal Server Errorは素晴らしいアイデアです。 –

+0

@ 500-InternalServerErrorこのシナリオでIOCを使用しないと提唱していますか? – Jon

答えて

0

はILoggerです工場ではなく、実際のILoggerです渡しです。次に、ユーザーの引数を指定してUserPressedPlayからファクトリを呼び出して、実際のLoggerインスタンスを作成することができます。

0

あなたのFileLoggerDirectoryPathプロパティを追加し、後でそれをintitializeことができます。

+0

IOCを使用してクラスをインスタンス化しないでください。 – Jon

+0

インスタンス化後に実行する必要がある追加のルールやコードを定義できるようなIOCコンテナのようなものもあります。また、読み込み専用のプロパティでプラグインのロガーを公開することもできます。どのような場合でも、ディレクトリパスを設定できるようにするには、ロガーへの参照が必要です。あなたがIOCでそれを行うことができれば、大丈夫です。 –

+0

読み取り専用プロパティはどのように機能しますか? – Jon

0

Expression.Newを使用すると、上記のパラメータでコンストラクタを動的に作成/呼び出すことができます。

Func<String, FileLogger> func = GetConsturctor<String, FileLogger>(); // Cache it somewhere. 

    FileLogger logger = func(@"C:\Loggerpath\"); // instantiate 

    static Func<TArg, TRes> GetConsturctor<TArg, TRes>() 
    { 
     Type resultType = typeof(TRes); 
     Type argType = typeof(TArg); 

     Type[] argumentArray = new Type[] { argType }; 
     ConstructorInfo constructor = resultType.GetConstructor(argumentArray); 

     ParameterExpression param = Expression.Parameter(argType); 
     Expression<Func<TArg, TRes>> result = Expression.Lambda<Func<TArg, TRes>>(
     Expression.New(constructor, param), param); 
     return result.Compile(); 
    } 
0

だから、DIは柔軟性が高く、カップリングは低いですが、しばしば必要ではありません。この特定のケースでは、それを追加する方法を心配することは過度の可能性があります。ここにGUIを持っているようですが、これはあなたがそれを設定するのに使っているFileLoggerクラスと一致するように設定されています。だから多分ここでのDIは過剰です。あなたのプラグインが今日使用するその他のタイプの​​がありますか?もしそうなら、工場オプションは潜在的に良いものになるでしょう。私は、GUIの言及に基づいて、ロガーの種類は1つしかないと考えています。その場合は、ここでDIを使用することでハングアップしないでください。 MyPluginクラスをテストする方法を見つけようとしていて、DIなしでそれを行う方法がわからない場合は、教えてください。この回答を展開して、問題を解決する方法を示します。

希望に役立ちます!あなたが何をしたいか

ブランドン

関連する問題