10

まず、インターフェイスまたは抽象クラス(.NET / C#の用語で)が抽象静的メソッドを持つことができない理由を理解しました。次に、私の質問は、最良の設計ソリューションに焦点を当てています。

私が欲しいのは、サードパーティベンダーからオブジェクトA、B、Cを取得した場合に、次のようなメソッドを持つヘルパークラスを持つことができるように、すべて独自の静的メソッドを持つ一連の「ヘルパー」クラスです。

AHelper.RetrieveByID(string id);
AHelper.RetrieveByName(文字列名);
AHelper.DumpToDatabase();

私のAHelper、BHelper、およびCHelperクラスはすべて基本的に同じメソッドを持っているので、これらのメソッドを、これらのクラスが派生するインターフェイスに移動することは理にかなっているようです。ただし、これらのメソッドを静的にしたいので、すべてのメソッドから派生するジェネリックインターフェイスまたは抽象クラスを使用できません。

これらのメソッドを常に非静的にしてから、最初に次のようなオブジェクトをインスタンス化することができます。

AHelper a = new AHelper();
a.DumpToDatabase();

ただし、このコードは私には直感的ではないようです。あなたの提案は何ですか?インターフェイスまたは抽象クラスの使用を完全に放棄する必要がありますか(現在の状況)、またはこれをリファクタリングして、探しているデザインを実現できますか?

4

10 に答える 10

5

私があなただったら、静電気を避けようとします。私見私はいつも、静的な道のりである種の同期の問題に遭遇しました。そうは言っても、テンプレートを使用した汎用プログラミングの古典的な例を提示しています。上記の投稿の 1 つで提示された Rob Copper のテンプレート ベースのソリューションを採用します。

于 2008-08-18T14:30:19.777 に答える
3

あなたの回答を見て、私は次の行に沿って考えています:

  • 型パラメーターを受け取り、型に基づいて期待されるロジックを実行する静的メソッドを作成できます。
  • 抽象ベースに仮想メソッドを作成し、具体的なクラスで SQL を指定できます。そのため、サブクラスの「専門家」ビット (SQL など) をカプセル化しながら、両方に必要なすべての共通コード (コマンドの実行とオブジェクトの返しなど) が含まれます。

もちろんあなた次第ですが、私は2番目のオプションを好みます。さらに詳しく説明する必要がある場合は、お知らせください。喜んで編集/更新いたします:)

于 2008-08-18T14:25:33.733 に答える
3

あなたの例に対する一般的な解決策として、これを行うことができます:

public static T RetrieveByID<T>(string ID)
{
     var fieldNames = getFieldNamesBasedOnType(typeof(T));
     QueryResult qr = webservice.query("SELECT "+fieldNames + " FROM "
                                     + tyepof(T).Name
                                     +" WHERE Id = '" + ID + "'");
     return (T) qr.records[0];
}
于 2008-08-18T14:30:03.053 に答える
2

個人的には、さらに考える前に、なぜ各型に静的メソッドが必要なのか疑問に思うでしょう..

共有する必要がある静的メソッドを含むユーティリティ クラスを作成しないのはなぜですか? (例えばClassHelper.RetrieveByID(string id)、またはClassHelper<ClassA>.RetrieveByID(string id)

この種の「障害物」に関する私の経験では、問題は言語の制限ではなく、私の設計の制限です..

于 2008-08-18T13:53:27.010 に答える
2

ObjectA と AHelper はどのように関連していますか? AHelper.RetrieveByID()と同じロジックですBHelper.RetrieveByID()

はいの場合、ユーティリティ クラス ベースのアプローチはどうですか (public static メソッドのみで状態のないクラス)

static [return type] Helper.RetrieveByID(ObjectX x) 
于 2008-08-18T13:57:02.260 に答える
2

戻り値の型だけを変更してメソッドをオーバーロードすることはできません。

別の名前を使用できます。

static AObject GetAObject(string id);
static BObject GetBObject(string id);

または、キャスト演算子を使用してクラスを作成できます。

class AOrBObject
{ 
   string id;
   AOrBObject(string id) {this.id = id;}

   static public AOrBObject RetrieveByID(string id)
   {
        return new AOrBObject(id);
   }

   public static AObject explicit operator(AOrBObject ab) 
    { 
        return AObjectQuery(ab.id);
    }

   public static BObject explicit operator(AOrBObject ab)
    { 
        return BObjectQuery(ab.id);
    } 
}

次に、次のように呼び出すことができます。

 var a = (AObject) AOrBObject.RetrieveByID(5);
 var b = (BObject) AOrBObject.RetrieveByID(5); 
于 2008-08-18T14:18:22.797 に答える
1

C#3.0では、以下のDumpToDatabase()のように、拡張メソッドを使用することで、静的メソッドをインターフェイスの一部であるかのように使用できます。

static class HelperMethods
 {  //IHelper h = new HeleperA();
    //h.DumpToDatabase() 
    public static void DumpToDatabase(this IHelper helper) { /* ... */ }

    //IHelper h = a.RetrieveByID(5)
    public static IHelper RetrieveByID(this ObjectA a, int id) 
     { 
          return new HelperA(a.GetByID(id));
     }

    //Ihelper h = b.RetrieveByID(5)       
    public static IHelper RetrieveByID(this ObjectB b, int id)
     { 
          return new HelperB(b.GetById(id.ToString())); 
     }
 }
于 2008-08-18T13:46:54.247 に答える
0

Stack Overflow でフィードバックを投稿するにはどうすればよいですか? 元の投稿を編集するか、「回答」を投稿しますか? とにかく、 AHelper.RetrieveByID() と BHelper.RetreiveByID() で何が起こっているかの例を挙げると役立つかもしれないと思いました

基本的に、これらのメソッドは両方とも、唯一のパラメーターとして疑似 SQL 文字列を受け取る Query メソッドを使用して、さまざまな汎用 (キャスト可能) オブジェクトを返すサード パーティの Web サービスに対抗します。

したがって、 AHelper.RetrieveByID(string ID) は次のようになります

public static AObject RetrieveByID(文字列 ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name FROM AObject WHERE Id = '" + ID + "'");

  return (AObject)qr.records[0];
}

public static BObject RetrieveByID(文字列 ID)
{
  QueryResult qr = webservice.query("SELECT Id,Name,Company FROM BObject WHERE Id = '" + ID + "'");

  return (BObject)qr.records[0];
}

うまくいけば、それは役に立ちます。ご覧のとおり、2 つのメソッドは似ていますが、返されるオブジェクト タイプが異なるため、クエリがかなり異なる場合があります。

ああ、そしてロブ、私は完全に同意します-これはおそらく私のデザインの制限であり、言語ではありません. :)

于 2008-08-18T14:05:17.750 に答える
0

ポリモーフィックな動作をお探しですか? 次に、インターフェースと通常のコンストラクターが必要になります。コンストラクターの呼び出しについて直感的でないのは何ですか? ポリモーフィズムが必要ない場合 (現在は使用していないように思えます)、静的メソッドをそのまま使用できます。これらがすべてベンダー コンポーネントのラッパーである場合は、VendorBuilder.GetVendorThing("A") のようなファクトリ メソッドを使用して、IVendorWrapper 型のオブジェクトを返すことができるかもしれません。

于 2008-08-18T14:07:03.240 に答える
0

marxidadちょっと注意してください。ジャスティンは、SQLは型によって大きく異なるとすでに言っているので、型によってまったく異なるものになる可能性があることに基づいて作業しました。したがって、問題のサブクラスに委譲します。 . あなたのソリューションはSQLをタイプに非常に緊密に結合します(つまり、SQLです)。

rptony静的に関する同期の問題の可能性についての良い点、私が言及できなかったもの、ありがとう:) また、そのロブ・クーパー(銅ではない) ところで;) :D (編集:場合に備えてそれについて言及すると思いました'タイプミスだと思いますので問題ありません!)

于 2008-08-18T14:42:11.407 に答える