[英]Generic method where T implements Interface<T>
我正在嘗試創建一個通用的數據檢索過程。 我目前可以使用的軟件,但是其中一部分似乎並不正確,我希望有一種更好的方法來完成它。
因此,想法是我為數據庫中的每個表都有類,這是一個類的示例:
public class CMCGRGRGROUP : IFacetsObject<CMCGRGRGROUP>
{
public int GRGR_CK { get; set; }
public string GRGR_NAME { get; set; }
public string GRGR_ADDR1 { get; set; }
public IEnumerable<CMCGRGRGROUP> ToObject(DataTable table)
{
return table.AsEnumerable().Select(row =>
{
return new CMCGRGRGROUP
{
GRGR_CK = Convert.ToInt32(row["GRGR_CK"]),
GRGR_NAME = row["GRGR_NAME"].ToString(),
GRGR_ADDR1 = row["GRGR_ADDR1"].ToString()
};
});
}
}
您會注意到該類實現了自己類型的接口。 該接口僅定義了一個稱為ToObject
的方法,該方法用於將數據表轉換為該特定類型的類:
public interface IFacetsObject<T>
{
IEnumerable<T> ToObject(DataTable obj);
}
現在,這是我用來執行查詢的方法:
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj) where T : new()
{
using (var conn = new AseConnection(_conn))
{
conn.Open();
var cmd = new AseCommand(sql, conn);
var dt = new DataTable();
var da = new AseDataAdapter(sql, conn);
da.Fill(dt);
return obj.ToObject(dt); //this is the interface method
}
}
因此,主要問題是:通用方法如何知道T應該實現IFacetsObject<T>
? 這樣,我不必傳遞IFacetsObject<T>
作為參數。 理想情況下,我可以將返回線更改為以下形式:
return T.ToObject(dt);
並這樣稱呼它:
var result = ExecuteQuery<CMCGRGRGROUP>(sql).Take(5);
而不是像這樣:
var result = ExecuteQuery<CMCGRGRGROUP>(sql, new CMCGRGRGROUP()).Take(5);
我承認我還不太熟悉泛型,因此實現中可能存在某些不正確的地方。
您可以在ExecuteQuery方法上添加約束。 您已經有一個:要求T是可更新的。 您可以這樣聲明:
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj)
where T : IFacetsObject<T>, new()
{
using (var conn = new AseConnection(_conn))
{
conn.Open();
var cmd = new AseCommand(sql, conn);
var dt = new DataTable();
var da = new AseDataAdapter(sql, conn);
da.Fill(dt);
return obj.ToObject(dt); //this is the interface method
}
}
因此,現在知道T是IFacetsObject<T>
。 您現在可以執行以下操作:
public IEnumerable<T> ExecuteQuery<T>(string sql)
where T : IFacetsObject<T>, new()
{
using (var conn = new AseConnection(_conn))
{
conn.Open();
var cmd = new AseCommand(sql, conn);
var dt = new DataTable();
var da = new AseDataAdapter(sql, conn);
da.Fill(dt);
return new T().ToObject(dt); //this is the interface method
}
}
哪個IMO仍然很丑陋。
編輯回應:
請注意,您不能調用T.ToObject-接口不能定義靜態方法。 解決方法是使用new來創建T的新實例並調用instance方法。
您需要對接口進行一般約束。 像這樣聲明:
public interface IFacetsObject<T> where T : IFacetsObject<T>
{
IEnumerable<T> ToObject(DataTable obj);
}
為了使它起作用,您還必須像這樣更改聲明:
public IEnumerable<T> ExecuteQuery<T>(string sql, IFacetsObject<T> obj)
where T : IFacetsObject<T>, new()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.