2012-01-05 8 views
4

API(1.4と1.5)の2つの異なるバージョンに接続できる必要があります.Foo APIを呼び出すことができます。また、APIに接続して結果を処理するコードは実質的に重複していますが、唯一の違いは2つのAPIから返されるデータ型です。重複を取り除くためにこれをどのようにリファクタリングすることができますか?唯一の違いが1つの変数の型である場合、重複コードをリファクタリングするか?

(1.5 APIを呼び出して、私自身のクラス)

public class Foo14Connector 
{ 
    public void GetAllCustomers() 
    { 
     var _foo = new Foo14WebReference.FooService(); 
     Foo14WebReference.customerEntity[] customers = _foo.getCustomerList; 
     foreach (Foo14WebReference.customerEntity customer in customers) 
     { 
      GetSingleCustomer(customer); 
     } 
    } 
    public void GetSingleCustomer(Foo14WebReference.customerEntity customer) 
    { 
     var id = customer.foo_id; 
     // etc 
    } 
} 

、ほぼ正確な複製クラスFoo15Connector.csで

public class Foo15Connector 
{ 
    public void GetAllCustomers() 
    { 
     var _foo = new Foo15WebReference.FooService(); 
     Foo15WebReference.customerEntity[] customers = _foo.getCustomerList; 
     foreach (Foo15WebReference.customerEntity customer in customers) 
     { 
      GetSingleCustomer(customer); 
     } 
    } 
    public void GetSingleCustomer(Foo15WebReference.customerEntity customer) 
    { 
     var id = customer.foo_id; 
     // etc 
    } 
} 
(1.4 APIを呼び出して、私自身のクラス)Foo14Connector.csで

API上の1つのメソッド呼び出し(数百のうち)が1.5で新しいパラメータを持つため、2つの異なるコネクタが必要です。

クラスFoo14WebReference.customerEntityとFoo15WebReference.customerEntityの両方のプロパティが同じです。コネクタは異なるプロジェクトにある場合は

+1

'Foo14WebReference.customerEntity'と' Foo15WebReference.customerEntity'は、共通のインターフェイスまたは基本型を共有していますか? –

+1

両方のコネクタは同じプロジェクトにありますか? –

+0

動的タイプを使用できますか? – Sneal

答えて

5

、これは容易な状況が解決することである。

は、新しいクラスファイルを追加し、それConnectorCommonを呼び出し、共通のコードのすべてをコピーしますが、名前空間を削除します。このクラスを部分クラスにし、クラス(ファイルではない)の名前をConnectorのように変更します。

各プロジェクトにリンクを追加する必要があります。

次に、現在のコネクタクラスからすべてのコードを削除し、クラス(ファイルである必要はない)の名前を部分クラスと同じに変更し、名前空間を参照するusingステートメントを追加します。

これはあなたが探しているものを取得する必要があります。

ので、作業が完了したときにあなたがいるでしょう:

ファイルConnectorCommon:

public partial class Connector 
{ 
    public void GetAllCustomers() 
    { 
     var _foo = new FooService(); 
     customerEntity[] customers = _foo.getCustomerList; 
     foreach (customerEntity customer in customers) 
     { 
      GetSingleCustomer(customer); 
     } 
    } 
    public void GetSingleCustomer(customerEntity customer) 
    { 
     var id = customer.foo_id; 
     // etc 
    } 
} 

ファイルMagento15Connector

using Foo15WebReference; 

partial class Connector 
{ 
} 

ファイルMagento14Connector

using Foo14WebReference; 

partial class Connector 
{ 
} 

更新

このプロセスは、最初は少し混乱する可能性があります。明確にするために

、次の2つのプロジェクト間の共通ファイルソースコードを共有しています。

実際のクラスは、各プロジェクトの名前空間を持つ特定のクラスです。 partialキーワードを使用すると、共通ファイルを各プロジェクトの実際のプロジェクトファイル(つまりMagneto14)と組み合わせて、コンパイル時にそのプロジェクト内にフルクラスを作成できます。

最も難しいのは、共通ファイルを両方のプロジェクトに追加することです。

これを行うには、2番目のプロジェクトでAdd Existing Item...メニューを選択し、共通ファイルに移動してAddボタンの横にある右向きの矢印をクリックします。

ドロップダウンメニューから、Add as linkを選択します。これにより、参照がファイルに追加され、2番目のプロジェクトに追加されます。ソースコードは両方のプロジェクトに含まれ、共通ファイルへの変更は両方のプロジェクトで自動的に利用可能になります。

アップデート2

私は時々それが私の通常のプログラミング環境であるため、VBは、このようなタスクを作る方法を簡単に忘れます。

C#でこの作業を行うためには、もう1つの工夫が必要です:Conditional compilation symbols。これは、共通コードの開始を私が望むものよりも少し冗長にしますが、共通コードの単一のセットで作業できることを保証します。

このトリックを使用するには、条件付きコンパイルシンボルを各プロジェクトに追加します(All Configurationsに設定されていることを確認してください)。たとえば、Magento14プロジェクトでは、Ver14を追加し、Magento15プロジェクトにはVer15を追加します。共通ファイルに続いて

、次のような構造を持つ名前空間を置き換えます

#if Ver14 
using Magneto14; 
namespace Magento14Project 

#elif Ver15 
using Magneto15; 
namespace Magento15Project 

#endif 

これは、適切な名前空間とusingsが共通のコードがにコンパイルされているプロジェクトに基づいて含まれていることを確認します。

すべての共通のusingステートメントは、共通ファイルに保持する必要があります(コンパイルするには十分です)。

+0

プロジェクトの境界を越えて部分クラスを実行できますか?しかし、ConnectorCommonはcustomerEntity型が何であるかを知るために何を参照していますか? 1.4 APIを参照する場合、15コネクタは動作しません。逆も同様です。 –

+0

部分クラス:いいえ、各プロジェクトに別々のクラスを作成しています。そのトリックは、これらのクラスの間でConnectorCommonのコードを共有し、各プロジェクト内で実際のクラスを持つことです。これは部分クラスであるため、Connectorcommonは実際のクラスからusingステートメントを選択し、各プロジェクト内で正しくコンパイルします。 –

+0

私はそれを行ってみましょう:) –

0

両方の実装に共通するインターフェイスを導入する必要があります。プロジェクトが同じ言語で書かれ、異なるプロジェクトにある場合は、両方のプロジェクトが参照する共通のプロジェクトを導入することができます。あなたは、コントロールのインバージョン(Google、依存性注入、サービスロケータ、または工場パターン)を使用して、バックグラウンドでバックグラウンドでさまざまな実装を入れ替えることができるように、あなたのインターフェースに依存するように動いています。あなたのための

難しさは次のようになります。実装で

1)パブリック静的メソッドは、潜在的に意味をなさないdoesntの一の実施クラスすなわちFoo14ConnectorまたはFoo15Connectorのコードを持っている)インタフェース 2を介して静的に公開することができません

+0

両方のWeb参照プロジェクトを制御できないために私が提案していることができない場合は、静的ダッキングを試すことができます。 – Dessus

1

FooConnectorsが封印されておらず、新しいインスタンスを作成するコントロールがある場合は、独自のコネクタを派生させて同時にインターフェイスを実装することができます。 C#では、基本クラスから継承するだけでメンバーを実装できます!

public IFooConnector { 
    void GetAllCustomers(); 
} 

public MyFoo14Connector : Foo14Connector, IFooConnector 
{ 
    // No need to put any code in here! 
} 

、その後

IFooConnector connector = new MyFoo14Connector(); 
connector.GetAllCustomers(); 
関連する問題