2009-03-02 14 views
2

私はデータベースアクセスのための私の慣例をカプセル化した単純な基本クラスを作成しようとしています。私は一般にproductIDに基づいて製品を選択するために "products_retrieve_product"という名前のsprocを作成します。基本クラスの "Retrieve"メソッドで、派生クラスが定義する型を返すようにしたいと思います。 Genericsで可能なことを達成しようとしていますか?基本クラスのメソッドを通じて汎用型を返すにはどうすればよいですか?

public class MyBaseClass<T> : T 

現在ジェネリックでは不可能である:あなたが本当に行うことができるために必要なものをクラス定義の中でこのようなものがあるので

public class MyBaseClass <T> 
{ 
    private string _className; 

    public MyBaseClass() 
    { 
     _className = this.GetType().Name; 
    } 

    public virtual T Retrieve(int ID) 
    { 
     Database db = DatabaseFactory.CreateDatabase(); 
     DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", _className)); 
     db.AddInParameter(dbCommand, String.Format("@{0}ID", _className), DbType.Int32, ID); 

     using (IDataReader dr = db.ExecuteReader(dbCommand)) 
     { 
      if (dr.Read()) 
      { 
       BOLoader.LoadDataToProps(this, dr); 
      } 
     } 
     return (T)this; 
    } 
} 

答えて

2

私はあなたがこのような何かをしたいと思いますこのプログラムを実行すると、Fooのタイプ名がコマンドラインに表示されます。明らかにこれは人為的な例ですが、おそらくMyBaseClass.Retrieve()のデータベースから読み込むときにもっと便利なことができます。

キーはTに制約を追加して、クラス自体のインスタンスでなければなりません。このようにして、サブクラス化の際にジェネリック型としてサブクラスを指定することができますMyBaseClass<T>.

これは良いアイデアであるかどうかはわかりませんが、実行できるように見えます。

-1

はありません、それは、ないです。

あなたがする必要があることは、工場が生産するものから工場を分けることです(あなたはTを構築する別のクラスが必要です。次に、T、場合によっては拡張メソッドで作業するヘルパーメソッドを提供する必要があります)。

1

あなたの例では、私はバーを返すために、私のFooクラスを望んでいた場合とき(...)取得呼び出されます。

class MyBaseClass<T> where T : MyBaseClass<T>, new() 
{ 
    public T Retrieve() 
    { 
     return new T(); 
    } 
} 

class Foo : MyBaseClass<Foo> 
{ 
} 

class Program 
{ 
    public static void Main() 
    { 
     Foo f = new Foo(); 
     Foo f2 = f.Retrieve(); 
     Console.WriteLine(f2.ToString()); 
    } 
} 

とき:

public class Foo : MyBaseClass<Bar>{} 
+0

私がこだわっている部分は、「検索」方法は派生型にオブジェクトをキャストする方法です。 –

+0

メソッドの戻り値の型として既に宣言されているので、キャストする必要はありません。 "return this;"あなたが必要とする仕事はありますか? –

+0

私はあなたが派生クラスにあるメソッドについて話していると思うが、私は基本クラスの派生クラスに基づいて型を返すメソッドを実装したいと思います。 –

0

ええと、私たちはリフレクションを使ってクラス名を取得しています。 BOLoaderは、間違いなくリフレクションを使用していくつかのプロパティをロードしています。なぜ反射に完全にコミットしないのですか?

BOLoaderはこの「返品タイプ」のゲームを気にしません。どうして?

public static class MyBaseClassExtender 
{ 
    public static void Retrieve(this MyBaseClass entity, int ID) 
    { 
     string className = entity.GetType().Name; 
     Database db = DatabaseFactory.CreateDatabase(); 
     DbCommand dbCommand = db.GetStoredProcCommand(String.Format("{0}s_Retrieve_{0}", className)); 
     db.AddInParameter(dbCommand, String.Format("@{0}ID", className), DbType.Int32, ID); 

     using (IDataReader dr = db.ExecuteReader(dbCommand)) 
     { 
      if (dr.Read()) 
      { 
       BOLoader.LoadDataToProps(this, dr); 
      } 
     } 
    } 
} 

次に、あなただけ言う:

Foo myFoo = new Foo(); 
myFoo.Retrieve(2); 
関連する問題