2016-03-21 6 views
2

を使用。私はプリズム&ユニティを使用しています。本当に私は解決策でPrism/Unityを何とか使うことができない限り、それは問題ではないと思います。は、C#で、私はタイプ(T)に基づいて、一般的な、特定の実装を使用することができ、私は可能な限り一般的なようですWPF/MVVM /エンティティFrameworkでクラス構造を作成しようとしています

私はセットアップで、私はタイプ(T)に固有のコードを実行する必要があるまで、完璧に動作するシステムを持っています。

私が本当に希望することはそう、私はそれが一般的なバージョンを使用したい、何とかタイプTが一致する派生クラスを持っている場合、システムは、クラスの非ジェネリックバージョンを使用することです。

私は、基本クラスを持つスーパー骨抜き例で

public class BaseClass<T> 
{ 
    public T MyObject; 

    protected virtual int GetErrorCount() 
    { 
     int errorCount = 0; 

     if (MyObject == null) 
      errorCount++; 

     return errorCount; 
    } 
} 

クラスとサブクラス:

public class StringClass : BaseClass<String> 
{ 
    protected override int GetErrorCount() 
    { 
     int errorCount = base.GetErrorCount(); 

     if (MyObject != null && MyObject.Length < 5) 
      errorCount++; 

     return errorCount; 
    } 
} 

と実装クラス:

public class ImplementationClass<T> 
{ 
    public BaseClass<T> MyBaseObject; 

    public ImplementationClass() 
    { 
     // If T is a string I want to use StringClass instead of the base 
     // And it should happen automagically 
     MyBaseObject = new BaseClass<T>(); 
    } 
} 

私はいくつかを持っています複雑なスイッチを含むこの問題を回避するためのアイデアや、POCOクラスのbu(ロジックのデータのロジック)へのロジックの投げ込みそれは私がしたいことではありません。

私は実際のタイプを解決する必要があるときにはいつでも使用されるディクショナリとルックアップクラスを使用するというアイデアを捨てましたが、実際にプリズムがしていることがあるので、それを理解することはできません。

私は一般的に可能な限りこれを実現することができる方法上の任意のアイデア?


これについてはフィードバックがありましたか?私は何を気にする必要がありますか?

ソリューション(MyBaseObjectがあまりにも変更することが可能になります):

public static class HelperExt 
{ 
    internal static IEnumerable<Type> GetInhiritingTypes(this Type fatherT) 
    { 
     return fatherT.Assembly.GetTypes().Where(t => t.IsSubclassOf(fatherT) && !t.IsAbstract); 
    } 
} 

public class ImplementationClass<T> 
{ 
    private BaseClass<T> _myBaseObject; 
    public BaseClass<T> MyBaseObject 
    { 
     get { return _myBaseObject; } 
     set 
     { 
      Type instType = typeof(BaseDataViewModel<T>).GetInhiritingTypes().FirstOrDefault(t => t.BaseType.GetGenericArguments().Contains(typeof(T))); 
      if (instType != null) 
       SetProperty(ref _myBaseObject, (BaseClass<T>)Activator.CreateInstance(instType)); 
      else 
       SetProperty(ref _myBaseObject, value); 
     } 
    } 

    public ImplementationClass() 
    { 
     // If T is a string I want to use StringClass instead of the base 
     // And it should happen automagically 
     MyBaseObject = new BaseClass<T>(); 
    } 
} 
+0

それが集約代わりの継承を使用する意味がありますか? – BatteryBackupUnit

+0

私はここでどのように集約できたか分かりません。少なくとも問題を解決しながらも、一般的な実装を失うこともありません。 –

+0

ジェネリック薬の使用は私には無意味なようです。しかし、あなたは、あなたが使用することをお勧めしますタイプごとに1つずつ、複数のプライベートメンバを宣言し、次にあなたが 'ImplementationClass 'のインスタンスを作成するにはどうすればよいT. –

答えて

1

あなたは、いくつかの反射、最初にこのヘルパー関数でこれを行うことができます。そして、

public static IEnumerable<Type> GetInhiritingTypes(this Type fatherT) 
    { 
     return fatherT.Assembly.GetTypes().Where(t => t.IsSubclassOf(fatherT) && !t.IsAbstract); 
    } 

Type genericType = typeof(string); 
Type typeToInstantiate = typeof(BaseClass<String>).GetInheritingTypes().FirstOrDefault(t=>t.GetGenericsArguments().Contains(genericType)); 
if (typeToInstantiate != null) 
    MyBaseObject = (BaseClass<T>)Activator.CreateInstance(typeToInstantiate); 
else 
    MyBaseObject = new BaseClass<T>(); 

しかし、このような方法では "安全"はほとんどありません。クラス名を取り、そのクラスのインスタンスをインスタンス化するファクトリ関数を書くこともできます。

+0

私はこれを動作させようとしています。私はそれを小さなステップに分割しました。 'typeToInstantiate'が正しい親タイプ(すなわち' StringClass')を持っているが、 'GetGenericArguments()'が空の配列を返すことがわかります。何か案は。 –

+0

ええ...それを考え出した。 'instTypes.FirstOrDefault(t => t.BaseType)を実行する必要があるように見えます。GetGenericArguments()。Contains(genType)) '< - キーはBaseTypeです。 –

関連する問題