2016-04-05 12 views
-2

文字列を入力として取得し、各文字列ごとに異なるクラスを初期化する必要があります。異なる文字列に基づいて異なるクラスを入力として初期化する

文字列が "Sa"でGetSystemStatusクラスを初期化する必要があるとします。
文字列が "sw"で、SystemRotateクラスを初期化する必要があるとします。私は、クラスを初期化する必要があり、各文字列の場合 :

私の提案されたソリューションは、

  1. スイッチケースです。これは面倒です。私は約1500本の弦を持っています。
  2. 私の文字列とクラスを辞書にキー値のペアとして格納し、目的の結果を得る。それでも私は辞書を維持する必要があります。辞書にないものがあると、プログラムは失敗します。
  3. 文字列とともにクラス名を渡します。その後、文字列を分割し、クラス名を取得します。私は入力文字列にクラス名を持つことができるかどうかは分かりません。

解決策を提案する人もいます。リンクやコードの一部は高く評価されます。私の提案は非常に多くなり

おかげ Gopi

+0

1500文字列ごとに別々のクラスを初期化していますか、または大量に特定のクラスを初期化していますか? – oppassum

+0

ここで性能と問題はありますか?それはどのくらい頻繁に呼び出されますか?ここでは、別のオプションが表示されています: 1.クラスにアクセスできる場合は属性を適用し、リフレクションを使用して適切なものを探します。 2.スタティック登録ポイント を使用してください。3.カスタムコードジェネレータ – Toxantron

答えて

0

私は反射ソリューションを説明します。それがすぐにコンパイルされない場合は、私に教えてください。私は正しいメンバー名を保証できないので、これをメモリから書きました。

public class SomeAttribute : Attribute 
{ 
    public string Input { get; set; } 
} 

[Some(Input = "sw")] 
public class SystemRotate 
{ 

} 

public object Get(string input) 
{ 
    // Define where to search for types 
    var type = (from assembly in AppDomain.Current.GetAssemblies() 
       from type in assembly.GetTypes() 
       let att = type.GetCustomAttribute<SomeAttribute>() 
       where att != null && att.Input == input 
       select type).FirstOrDefault(); 
    return Activator.CreateInstance(type); 
} 
+0

私はこれを考慮していませんでしたが、私はこのソリューションがクラスをインスタンス化して文字列属性を読み取る必要がないのが好きです。賢い – TheRotag

+0

ありがとうヒーロー。いくつかの調整を行いました。 – user3012974

+0

私は助けてくれると嬉しいです。 ;-) – Toxantron

0

@Toxantronが示唆された各クラスのサブクラスに対応する文字列のプロパティを定義するいくつかの抽象クラスを持っています。リフレクションを使用して適切なクラス/タイプを見つけ出し、インスタンス化します。それはこのようになります:

public abstract class BaseClass 
{ 
    public abstract string InputString { get; } 
} 

public class ChildClass1 : BaseClass 
{ 
    public override string InputString { get { return "a"; } } 
} 

public class ChildClass2 : BaseClass 
{ 
    public override string InputString { get { return "b"; } } 
} 

は、その後、あなたがこのような方法で何かに正しいクラスをインスタンス化できます。あなたはまた、作成したインスタンスのリストをキャッシュすること

public BaseClass GetClassFromString(string inputString) 
{ 
    return typeof(BaseClass).Assembly.GetTypes() 
     .Where(x => typeof(BaseClass).IsAssignableFrom(x)) 
     .Select(x => Activator.CreateInstance(x)) 
     .FirstOrDefault(x => x.InputString == inputString); 
} 

最初の後、そのので、これはより効率的に実行されます。

編集:ここで私が述べたキャッシングの例です:

private static Dictionary<string, Type> _stringTypeDictionary; 

public BaseClass GetClassFromString(string inputString) 
{ 
    // If cache doesn't already exist, create it 
    if (_stringTypeDictionary == null) 
    { 
     _stringTypeDictionary = typeof(BaseClass).Assembly.GetTypes() 
     .Where(x => typeof(BaseClass).IsAssignableFrom(x)) 
     .Select(x => Activator.CreateInstance(x)) 
     .ToDictionary(x => x.InputString, x => x.GetType()); 
    } 

    if (_stringTypeDictionary.ContainsKey(inputString)) 
     return Activator.CreatInstance(_stringTypeDictionary[inputString]) as BaseClass; 
    else 
     return null; // May want to throw exception here...that's up to you 
} 
+2

しかし、すべてのタイプをインスタンス化するだけで、パフォーマンスが大幅に低下します。 – Toxantron

+1

合意。しかし、より効率的なオプション(リストや辞書の維持など)は、OPによって撃墜されています。あなたは各タイプ**を一度**インスタンス化し、結果を(辞書の中で)キャッシュしておけば、将来の呼び出しでその辞書を使うことができます。既にキャッシュされていない新しいクラスが表示される唯一のケースは、(アセンブリを動的にロードしている場合を除いて)アプリケーションが再起動された場合で、次のアクセスによってキャッシュが再生成されます。 – TheRotag

+0

合意。しかし、これは状態の少ないクラスの動作を必要とします。 OPが何らかのフィードバックを出さない限り、私たちはここでやっていると思います。 – Toxantron

関連する問題