0

まれなデータベースのドライバーのラッパーを作成しています。具体的には、未加工のクエリ コードを実装しているため、当然、できるだけ多くの速度が必要です。これは、大規模な e コマース ソリューションに実装される予定です。

これにより、動的型とキャストを先延ばしにしました。実際のデータ型に直接アクセスしたい。

私が必要とする機能は、一般的なフィールドを持つ基本パラメーター クラスと、それぞれ 1 つの具体的に型指定されたフィールドを持つ一連の子クラス (int、long、double、string、byte[]、object、およびリスト、およびこれらの各タイプのリスト)。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) { }
}

私の実装では、基本クラスの配列を宣言する必要があります。これにより、作業中にスパナがスローされます。

これを行うためのより良い方法があると確信しています。インターフェイスを調べましたが、それらにも型が必要であり、基本型の配列が共通の型を共有しているため、ジェネリックを機能させることができませんでした。

前述の配列を変更すると、本質的に循環する他の複雑さが導入されます。

私が探しているものを実装するための最も効率的な方法、またはそれにできるだけ近い方法は何ですか?

EDIT 実装 (ジェネリックでは機能しません):

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

3 に答える 3

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) { }
}

編集:これの基本クラスと、この投稿に基づいたコレクションクラスを作成します ジェネリック型のコレクション

于 2012-09-29T14:52:29.883 に答える
1

必要なメソッド/プロパティを使用してインターフェイスを作成します。

public interface IGlobalQueryParam { 

  string ToString();

  . . . 

} 

次に、damdum answer のようにジェネリック クラスを使用し、インターフェイスを実装します。

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)。上記の例のように、値を文字列に変換します。

于 2012-09-29T15:18:15.143 に答える
0

最後に、オブジェクトとの間で値をキャストしてボックス化する元のコードに戻りました。オブジェクトの継承が目的の型を実装したため、ジェネリックは何も追加しませんでした。また、ジェネリックが削除されると、インターフェースは何も追加しませんでした。

于 2012-09-30T01:00:55.713 に答える