2009-03-02 45 views
2

我一直在試圖創建一個簡單的基類來封裝我的數據庫訪問的一些約定。我通常會創建一個名爲「products_retrieve_product」的存儲區,以根據productID選擇一個產品。我希望基類中的「Retrieve」方法返回派生類在其定義中提供的類型。我正試圖用泛型來實現嗎?如何通過基類中的方法返回泛型?

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

我認爲,你想要做這樣的事情:

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()); 
    } 
} 

當你運行該程序,Foo的類型名稱將打印在命令行中。顯然這是一個人爲的例子,但是也許你可以在MyBaseClass.Retrieve()從數據庫加載時做更有用的事情。

關鍵是在T上添加一個約束,以便它必須是類本身的一個實例。這種方式可以指定子類作爲子類的通用類型MyBaseClass<T>.

我不完全確定這是否是一個好主意,但它看起來可以完成。

-1

不,它不是,因爲你真正需要的是能夠做的就是這樣的類定義:

public class MyBaseClass<T> : T 

目前是不可能的仿製藥。你需要做的是將工廠從工廠生產中分離出來(你需要一個單獨的類來構建T,然後你應該提供幫助者方法來處理T,可能是擴展方法)。

1

當然。在您的例子,如果我想我的Foo類檢索時返回酒吧(...)被調用:

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

我卡上的部分是「檢索」方法是如何鑄就的對象爲派生類型。 – 2009-03-02 19:37:24

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); 
相關問題