2017-01-15 11 views
1

私のデザインには影響しませんが、コードとパフォーマンスの将来の変更に影響するケースを見つけました。コンストラクタによるクラスフィールドの自動初期化

私のクラスは以下の通りです:

public sealed class Commands { 
public interface ICommand { 
    string commandName { get; set; } 
} 

public ICommand Maintain; 
public ICommand Dispatch; 
public ICommand Memorize; 
//............// 

private class ReckonCommand : ICommand { 
    public string commandName { get; set; } 

    public ReckonCommand (string name) { 
     this.commandName = name; 
    } 
} 

public Commands() { 
    Maintain = new ReckonCommand ("Maintain") as ICommand; 
    Dispatch = new ReckonCommand ("Dispatch") as ICommand; 
    Memorize = new ReckonCommand ("Memorize") as ICommand; 
} 

このアプローチは、コマンドクラスで各ICommandの変数を初期化し、手動で必要になります。したがって、フィールドがより多くなると、維持するのが難しくなります。

代わり、動的なアプローチは以下の通りです:

public ICommand Maintain; 
public ICommand Dispatch; 
public ICommand Memorize; 
//............// 

private class ReckonCommand : ICommand { 
    public float commandName { get; set; } 
    //Stuff 

} 

public Commands() { 
    System.Reflection.FieldInfo[] _fields = GetType().GetFields(); 
    for (int i = 0; i < _fields.Length; i++) { 
     if (_fields [i].FieldType == typeof(ICommand)) { 
      _fields [i].SetValue (this, new ReckonCommand() as ICommand); 
     } 
    } 
} 

ただし、コマンドクラスが何回も(これはアイデアを得ることからあなたを妨げている場合、名前を無視)、そのパフォーマンスを初期化することが期待されています損失は​​ある時点で影響を受ける可能性があります。

私が使用しているこの特定のデザインの代替品はありますか?私の懸念は、Commandクラスのコンストラクタ内のすべてのICommandフィールドを自動的に初期化することです。手作業ではエラーが発生する可能性があります。

答えて

0

動的アプローチは完全に受け入れられます(大規模アプリケーションでは、説明したように問題を解決するためにすべてを使用します)。

ただし、クラスの静的コンストラクタで検出を実装し、その結果を静的コレクションに格納して、クラスのインスタンスが作成されるたびにリフレクションを実行する必要はありません。線に沿って

何か:

private static System.Collections.Generic.List<System.Reflection.FieldInfo> _fields; 

    static Commands() 
    { 
     _fields = new System.Collections.Generic.List<System.Reflection.FieldInfo>(); 

     var fields = typeof(Commands).GetFields(); 
     var commandType = typeof(ICommand); 

     foreach (var field in fields) 
     { 
      if (field.FieldType == commandType) 
      { 
       _fields.Add(field); 
      } 
     } 
    } 

    public Commands() 
    { 
     foreach (var field in _fields) 
     { 
      field.SetValue(this, new ReckonCommand() as ICommand); 
     } 
    } 
+0

素晴らしいアイデアは、あなたに感謝します。 2つのこと、i)varは直接型宣言よりもわずかに遅いことが知られています。 System.Collections.GenericとSystem.Reflectionのどちらの名前空間を使用するのかわからないか、この状況ではまったく問題ないのでしょうか? ii)fieldInfoのリストを取得したら、通常の値割り当てと同じ速さでSetValueメソッドを使用しますか? ICommandインターフェイスにもModify()というメソッドがあるため、私は尋ねています。 SetValueメソッドを使用するか、回避策を提示する必要がありますか? Modify()はCommandsクラスの初期化よりも頻繁に使用されます。 乾杯 –

+0

re var:varは、コンパイラが割り当ての変数の型を推論する際のコンパイル時の問題です。変数を明示的に入力するよりも実行時に遅くなることはありません。これを使用するのは、データ型が変更されたときに必要な変更の数を最小限に抑えるためです。 –

+0

re SetValue:SetValueではなくインターフェイス上で直接メソッドを使用するほうが、アプリケーションがわかりやすくなります。しかし、まず、ICommandオブジェクトの有効なインスタンスでCommandsクラスを生成する必要があります。これはループが現在実行しているものです。 Commandまたはループによって作成されたインスタンスがあれば、ICommandインタフェースのメソッドを使用してそのインスタンス(つまりModifyメソッド)を変更します。 –

関連する問題