2011-12-14 11 views
5

System.Data.SqlClient.SqlTransaction封印された)を継承したいとします。私はちょうどSqlTransactionの周りにラッパーを入れて、SqlTransactionの代わりに常にMyTransactionを使用したいと思います。 Implicit/Widening演算子を使用してMyTransactionSqlTransactionにキャストする方法はありますか?C#/ VB.NETで継承をFAKEする方法はありますか?

+5

'私はあなたがこのような何かをしたいと思う理由System.Data.SqlClient.SqlTransaction' =>を継承するとしますか? –

+4

ダーリンは正しいです。最初に鋼鉄桁に穴が必要な理由を教えてくれるのではなく、掘削を求めています。タイプが封印されているという事実は、私があなたがこの中から継承したくないという大きな赤旗です。なぜあなたはクラスのデザイナーの希望に反して作業しようとしていますか?彼らはあなたの最大の利益を心に持っています。あなたが本当に達成したいことを説明してください。なぜなら、密閉されたクラスから継承することは起こり得ないからです。 –

+1

リフレクションを使用してクラスの開封を行うことはできませんか? –

答えて

3

別のオプションがある場合は、Reflection.Emit()を使用して、選択したインターフェイスをSqlTransactionに追加してから、新しいMyTransactionクラスでその同じインターフェイスを使用し、クラスの代わりにインターフェイスを呼び出すことができます。

これは、作成したライブラリ内でのみ機能します。または、Reflectionを使用してロードされたタイプを特に変更することに注意してください。

+0

残念ながら、これはVB.NETにあり、Widening演算子はC#の "暗黙的"は私がちょうど見つけたものですが、このルートについても考えていたので動作していないようです...あなたが言ったように... – Denis

+0

@DenisあなたはC#でクラスをコーディングしてから、VBアプリケーションでDLLを使用することができます –

+1

@Denis Code in C#、Refelctorを使用してVBで逆アセンブルし、構文を参照してください。 – TomTom

6

内部トランザクション変数を持つクラスを作成し、メソッドとプロパティを公開することができます。種類のこのような:

public class MyTransaction 
{ 
    System.Data.SqlTransaction myTx = someConnection.CreateTransaction(); 

    public void CommitTransaction() : { 
     myTx.CommitTransaction() 
    } 
} 

ます。また、それはDbTransactionから継承し、その後、内側myTx変数を使用するように抽象的で仮想手続きを書き換える作ることができ、それは明白な本当の理由のために少し複雑になって開始します...

+1

絶対に! : - しかし、もし人がトランザクションをラップしたいなら、理由があるかもしれません! –

+0

彼はそれをやりたいと思うからといって、それが可能であっても、彼はすべきではありません。 –

+0

@Ramhound私は同意しますが、それでもこのような解決策が適している他の適切なケースを習得するには良い方法です –

3

クラスにメソッドを追加するだけの場合は、拡張メソッドを使用できます。これで内部状態にアクセスすることはできませんし、動作を上書きすることもできますが、限られた機能を追加することができます。私は封印されたクラスから継承する方法を知らない。

他にも述べたとおり、真のラッパーオブジェクトを作成できますが、元のオブジェクトの代わりに多態的に使用することはできません。

+0

これは.NET 2.0で拡張メソッドはありません...しかし、作成以来のものなので、拡張メソッドはとにかく動作しません。 – Denis

+0

これは.net 2のために重要ではありませんが、拡張メソッドは、拡張メソッド(操作されているオブジェクト)の最初のパラメータをキーにした辞書を使用して、独立したオブジェクトデータを追跡できます。これにより、内部状態に似ているがオブジェクトの外部に格納されたデータの「パーティション化」セットを提供できます。内部のメンバーにはリフレクションを介してアクセスできるので、コードを手に入れようとしている「醜い」方法に応じて、面白いことをすることができます。 –

+0

私はあなたが気にしないことを願っていますが、他の人がフレームワークのバージョンが限られていることを知るように.net2.0タグをあなたの質問に追加しました。 –

0

独自のMyTransactionクラスをSqlTransactionのラッパーとして定義できます。 MyTransaction内のプライベートフィールドにSqlTransactionのインスタンスを保持します。あなたのラッパーはSqlTransactionとの互換性はありませんが、SqlTransactionが実装しているインターフェイスと同じインターフェイスを実装すれば、かなり近づくことができます。

+0

これもうまくいくと思っていましたが、SqlClientのようなものがあります。本当に、私はこのクエストを開始した偽のこれまでいくつかの方法が必要SUXのSqlTransaction、ないIDbTransactionを望んでいるSQLCommand.Transaction ... – Denis

1

いいえ、カスタムクラスをSqlTransactionから継承したり、これを偽装したりすることはできません。

ただし、DbTransactionを使用することができるコンテキストでは、DbTransactionからカスタムトランザクションクラスを継承し、必要な機能をSqlTransaction内にラップすることができます。あなたが

class MyTransaction 
    { 
     private readonly SqlTransaction _transaction; 

     public MyTransaction(SqlConnection conn) 
     { 
      _transaction = conn.BeginTransaction(); 
     } 

     public SqlTransaction Transaction 
     { 
      get 
      { 
       return _transaction; 
      } 
     } 

     public static implicit operator SqlTransaction(MyTransaction t) 
     { 
      return t.Transaction; 
     } 
    } 
+0

私はうんこれも動作しますが、その後、あなたがのSqlTransaction – Denis

+0

を望んでいるSqlClient.SQLCommand.Transactionのようなものを持っていると思いましたラップされたオブジェクトの全体ラットネストに入ります...あなたはSystem.Data名前空間のすべてのカスタムラッパーをSQLバージョンをラップすることができます。それはあなたの要件が何であるか、なぜこれらのオブジェクトを最初の場所。目標を達成する他の(より良い)方法がありそうです。 –

1

:(それはIMO、恐ろしいアイデアと恐ろしいデザインであるように私は、それをお勧めしませんが)、あなたはこのような何かを行うことができますあなたは本当には暗黙の型変換をしたい場合

+1

また、これは特に汚い解決策です... –

+0

私はReflection.Emit()を試みたことがありません。私は見回すつもりですが、これがどのように機能するかについての良い例やチュートリアルはありますか? – Denis

1

拡張メソッドを作成できます。

public static class SqlTransactionExtensions 
{ 
    public static void DoSomething(this SqlTransaction transaction, int myParameter) 
    { 
     // do something here 
    } 
} 

クラスは静的である必要があります。 fistパラメータの前に魔法の単語thisを置きます。これは、あなたが拡張しているクラスの型でなければなりません。インターフェイスを拡張することもできます。この拡張メソッドを使用する場合は、作業中の同じ名前空間に定義されていない場合は、この拡張クラスの名前空間にusing namspaceが必要です。それはのSqlTransactionの定期的な方法であったかのように

あなたはその後、拡張メソッドを呼び出すことができます。

SqlTransaction t = new SqlTransaction(); 
t.DoSomething(5); 
+0

これは誰かがここに提案した良いアイデアですが、これには2つの問題があります。(1).NET 2.0を使用しています。(2).NET 2.0を使用していない場合は、 SqlTransactionの作成? (このsqlTransactionを作成した人またはそれが開始された時刻を追跡するとします) – Denis

+0

トランザクション用の静的ヘルパークラスを作成します。エクステンションクラスとよく似ていますが、 'this'キーワードはありません。 't.DoSomething(5);'でメソッドを呼び出すのではなく、 'TransactionsHelper.DoSomething(t、5);'でそれらを呼び出さなければなりません。拡張メソッドは実際には構文的な砂糖だけであり、通常のメソッドではできないことはできません。 –

2

OKので、継承を除外し、あなたが本当に解決したい課題に焦点を当て、(コメントに基づいて、スレッド)。

私は過去にすべての呼び出しをヘルパーライブラリで実行し、そのロジックを実装して成功しました。以前は、Microsoft Data Application Blockに掲載されているSqlHelperを使用しました。これはあなたのニーズに適応できるソースモジュールです。必要なロギングやその他のロジックを追加できます。

また、コードを非常に読みやすくします。 (INSERT年代のように)何のリターンを持っていないコマンドに対して単一の値を返すクエリのためのデータセット、

SqlHelper.ExecuteScalar()を返すクエリの

SqlHelper.ExecuteDataset()

SqlHelper.ExecuteNonQuery():あなたのようなことを行うことができます。

など

関連する問題