2012-09-29 44 views
0

我正在編寫圍繞罕見數據庫驅動程序的包裝。具體來說,我正在實施原始查詢代碼,所以我自然需要儘可能多的速度。這將在大型電子商務解決方案中實施。創建一個由子項實現的抽象字段的基類

這已經讓我失去了動態類型和鑄造。我想直接訪問實際的數據類型。

我需要的功能是具有通用字段的基本參數類和一系列具有一個特定類型字段的子類(每個數據庫類型爲int,long,double,string,byte [ ],對象和列表,以及這些類型中的每一個的列表)。 C#類型應該匹配數據庫類型。

這不是直截了當的,因爲在我的實現中,調用代碼需要看基類型,但基類型看不到子字段。

這裏是我到目前爲止的代碼:

private abstract class GlobalQueryParam 
{ 
    public readonly string Low; 
    // Val must be correctly typed 
    public abstract object Val; // requires casting; don't want, but works 
    protected string dbVal = "";   

    public string GetDBVal() 
    { 
     return this.dbVal; 
    } 

    public abstract bool SetDBVal(string value); 

    public GlobalQueryParam(string low) 
    { 
     this.Low = low; 
    } 
} 

public class GlobalQueryParamInt : GlobalQueryParam 
{ 
    /// <summary> 
    /// Represents the current literal value. Used in traversal actions. 
    /// </summary> 
    public override int Val; 

    public int Parse(string dbVal) 
    { 
     return (this.Val = int.Parse(dbVal)); 
    } 

    public override bool SetDBVal(string value) 
    { 
     if (value != "") 
     { 
      this.dbVal = value; 
      return int.TryParse(value, out this.Val); 
     } 

     return false; 
    } 

    public GlobalQueryParamInt(string low = "") : base(low) { } 
} 

在我的實現,我要聲明的基類的數組,這是在工程扔扳手。

我相信有更好的方法來做到這一點。我查看了接口,但它們也需要這種類型,並且由於共享一種通用類型的基本類型的數組,我無法使泛型生效。

如果我改變上述數組,我會介紹其他複雜性,這些複雜性本質上是循環的。

什麼是最有效的方式來實現我正在尋找,或儘可能接近它?

編輯 執行(不與泛型工作):

GlobalQueryParam[] trail = new GlobalQueryParam[dataPos+1]; // DOESN'T WORK 
    trail[0] = new GlobalQueryParamInt((this.TestParams[0].QueryLow - 1).ToString()); 
    trail[1] = new GlobalQueryParamInt((this.TestParams[1].QueryLow - 1).ToString()); 
    trail[2] = new GlobalQueryParamInt((this.TestParams[2].QueryLow - 1).ToString()); 
    trail[3] = new GlobalQueryParamInt((this.TestParams[3].QueryLow - 1).ToString()); 
    trail[4] = new GlobalQueryParamInt((this.TestParams[4].QueryLow - 1).ToString()); 
    trail[5] = new GlobalQueryParamInt((this.TestParams[5].QueryLow - 1).ToString()); 
    trail[6] = new GlobalQueryParamInt((this.TestParams[6].QueryLow - 1).ToString()); 
    trail[7] = new GlobalQueryParamInt((this.TestParams[7].QueryLow - 1).ToString()); 
+0

基類的數組有什麼問題?你關心的是「解析」方法嗎? – dumdum

+0

基類無法在後代類中看到類型字段。所以我要麼失去訪問權(這顯然是不可行的),要麼他們都必須是相同類型並被投射。這意味着拳擊和拆箱,這是每秒鐘數百萬英鎊的巨大性能。 – IamIC

+0

解析方法總是傳遞一個字符串,但可以輸出int,long,double,array [],List等。 – IamIC

回答

2

您想使用泛型

public abstract GlobalQueryParam{} 

public abstract class GlobalQueryParam<TValue>: GlobalQueryParam where TValue : struct 
{ 
    public readonly TValue Low; 
    public TValue Val; 
    protected TValue dbVal = default(TValue); 

    public TValue GetDBVal() 
    { 
     return dbVal; 
    } 

    public abstract bool SetDBVal(TValue value); 

    public abstract TValue Parse(string dbVal); 

    public GlobalQueryParam(TValue low) 
    { 
     this.Low = low; 
    } 
} 

public class GlobalQueryParamInt : GlobalQueryParam<int> 
{ 

    public int Parse(string dbVal) 
    { 
     return (this.Val = int.Parse(dbVal)); 
    } 

    public override bool SetDBVal(int value) 
    { 

     return true; 
    } 

    public GlobalQueryParamInt(int low = 0) : base(low) { } 
} 

編輯:創建這個和集合的基類根據此職位分類 Collection of generic types

+0

謝謝。我最關心的領域是瓦爾。這是鍵入的字段。 – IamIC

+0

對不起,我修好了。我錯過了使用泛型類型的最重要的屬性! – dumdum

+0

這基本上是我之前嘗試的(儘管我不知道當孩子是班級時,結構限制器在做什麼)。但它留下了我提到的陣列的問題。該數組是一個字段數組,因此具有不同的類型。然後我必須自己施放參數,這是我提到的循環問題。 – IamIC

1

創建具有方法/屬性的接口,你需要:

public interface IGlobalQueryParam { 

    string ToString(); 

    . . . 

} 

然後使用通用類,如damdum答案,實現接口:

private abstract class GlobalQueryParam<TValue> : IGlobalQueryParam where TValue : struct { 
    public readonly TValue Low; 
    public TValue Val;  
    protected TValue dbVal = default(TValue); 

    public TValue GetDBVal() 
    { 
    return dbVal; 
    } 

    public override string ToString() 
    { 
    return Val.ToString(); 
    } // ToString 

    . . . implement IGlobalQueryParam . . . 

} 

public class GlobalQueryParamInt : GlobalQueryParam<int> { 

    . . . 
} 

,然後創建和使用數組(或列表等)的接口:

IGlobalQueryParam[] trail = new IGlobalQueryParam[dataPos+1]; 
trail[0] = new GlobalQueryParamInt((this.TestParams[0].QueryLow - 1).ToString());  
trail[1] = new GlobalQueryParamInt((this.TestParams[1].QueryLow - 1).ToString());  
trail[2] = new GlobalQueryParamInt((this.TestParams[2].QueryLow - 1).ToString());  
trail[3] = new GlobalQueryParamInt((this.TestParams[3].QueryLow - 1).ToString());  
trail[4] = new GlobalQueryParamInt((this.TestParams[4].QueryLow - 1).ToString());  
trail[5] = new GlobalQueryParamInt((this.TestParams[5].QueryLow - 1).ToString());  

它仍然是不可能訪問每個項目的基礎價值沒有拳擊它(即IGlobalQueryParam屬性返回object),但可以創建接口的方法和屬性,以便在裝箱時完成底層值所需的操作 - 例如將值轉換爲字符串,如上例所示。

+0

謝謝。如何在接口中實現泛型Val?沒有實施,它是不可見的。 – IamIC

+1

@IanC:你不能沒有拳擊 - 但你可以在避免拳擊的價值上實施其他操作 - 我擴大了答案一點點。 – MiMo

+0

最後,我回到了我的原始代碼,該代碼將對象的值與對象進行投射和打包。泛型沒有添加任何內容,因爲對象繼承實現了所需的類型。一旦泛型被刪除,界面就沒有添加任何東西。 – IamIC

0

最後,我回到了原來的代碼,該代碼將值與對象進行投射和打包。泛型沒有添加任何內容,因爲對象繼承實現了所需的類型。一旦泛型被刪除,界面就沒有添加任何東西。