2012-03-30 8 views
1
namespace MyOldService 
{  
    public MyNewService.AddressList ToPrivateAddressList() 
    { 
     MyNewService.AddressList privAddrList = new MyNewService.AddressList(); 

     privAddrList.creator = (MyNewService.AddressListCreator)this.creator; 
     privAddrList.listId = this.listId; 
     privAddrList.listIdSpecified = this.listIdSpecified; 
     privAddrList.listName = this.listName; 
     privAddrList.listType = (MyNewService.AddressingMode)this.listType; 
     privAddrList.lastModified = this.lastModified; 
     privAddrList.lastModifiedSpecified = this.lastModifiedFieldSpecified; 

     if (this.siteList != null && this.listType == MyOldService.AddressingMode.XDAddressingModeSiteIDList) 
     { 
      privAddrList.siteList = new long[this.siteList.Length]; 
      Array.Copy(this.siteList, privAddrList.siteList, this.siteList.Length); 
     } 
     ... 

SOAP名前空間MyOldServiceで定義されたリストを、新しい名前空間MyNewServiceの同じレイアウトのクラスにコピーするために書かれました。 MyAldService名前空間をMyOtherAppServiceという3番目の名前空間にインポートすると、私のAddressListクラスがその3番目の名前空間のメンバーになり、そのように参照されるという問題があります。名前空間をメソッドに渡すにはどうすればよいですか?

コードを複製するのではなく、ジェネリックスに似たものを使ってコードを飾りたいと思っています(何とか調整してください)。 [各スニペットからわかるように、各ネームスペースから必要な複数のタイプがあります]。これにより、必要なネームスペースでアドレスリストを対応するクラスに変換できます。可能?

を編集してください。以下のコメントのいくつかに応じて、私がしようとしていることのより良い例を定義しようとします。

Web参照からWSDLからインポートされた3つのクラスです(いいえ、これらはコンパイルされません)。クラスAddressListはすべて同じレイアウトです。

namespace A 
{  
    enum Mode {}; 
    enum Creator {}; 

    class ATypeClass {} 

    public partial class AddressList 
    { 
     int id; 
     enum Mode mode; 
     enum Creator creator 
     long[] siteList; 
     ATypeClass[] cspList; 
    } 
} 

namespace B 
{  
    enum Mode {}; 
    enum Creator {}; 

    class BTypeClass {} 

    public partial class AddressList 
    { 
     int id; 
     enum Mode mode; 
     enum Creator creator 
     long[] siteList; 
     BTypeClass[] cspList; 
    } 
} 

namespace C 
{  
    enum Mode {}; 
    enum Creator {}; 

    class CTypeClass {} 

    public partial class AddressList 
    { 
     int id; 
     string name; 
     enum Mode mode; 
     enum Creator creator 
     long[] siteList; 
     CTypeClass[] cspList; 
    } 
} 

私は新しい方法で名前空間Aで部分クラスを拡張します:問題の一部は、クラス別の名前空間の各部分に加えて、あることを

namespace A 
{ 
    public partial class AddressList 
    { 
     public T.AddressList ToPrivateAddressList<T>() 
     { 
      T.AddressList privAddrList = new T.AddressList(); 

      privAddrList.creator = (T.Creator)this.creator; 
      privAddrList.id = this.id; 
      privAddrList.name = this.name; 
      privAddrList.mode = (T.Mode)this.mode; 

      if (this.siteList != null && this.listType == Mode.XDAddressingModeSiteIDList) 
      { 
       privAddrList.siteList = new long[this.siteList.Length]; 
       Array.Copy(this.siteList, privAddrList.siteList, this.siteList.Length); 
      } 
      ... 
     } 
    } 
} 

をお知らせまた、さまざまな名前空間からの列挙型です。私は右のあなたの問題をundesrtood場合

B.AddressList al1 = A.AddressList.ToPrivateAddressList<B>(); 
C.AddressList al1 = A.AddressList.ToPrivateAddressList<C>(); 
+3

をどこで参照の問題はありますか?フルネーム(namespacename.classname)のクラスを参照することはできますか? – Vlad

+0

私は彼がfqnなしでAddressクラスを参照することができると思うと思う – payo

+0

@payo:私はこの利便性は余分なコードの価値があるとは思わない:) – Vlad

答えて

0

あなたが探しているのは、汎用タイプ定義のインターフェイスとwhereキーワードです。

  • それは同じ名前
  • とプロパティを割り当てることによってこれを行い、その後、新しいを返すB
  • を入力する入力変換方法:私はあなたがこれを持っていることがわかります。コードから

    タイプBは

  • 種類が
  • クラスがある異なる名前空間に存在する(ただし、現在は、同じ名前を持つ)ことができますpartial

リフレクションを使用して同じ名前を使用する代わりに、各クラスに共通のプロパティを含むインターフェイスを実装させる必要があります。このように、あなたは時間型の安全性をコンパイル保持:

public interface ICommonAddress 
{ 
    int id { get; set; } 
    Mode mode { get; set; } 
    Creator creator { get; set; } 
    long[] siteList { get; set; } 
    ICommonAddress CreateAddress(); 
} 

あなたは今もちろん、あなたがプロパティにあなたのフィールドを変更する必要があります(このようなあなたのクラスをリファクタリングすることができますが、私はあなたのようにそれらを持っていると仮定していますすでにプロパティ:

// if your original partial class is auto-generated, it is ok to place 
// this definition in another file, it'll still work as long as 
// namespace, classname and compile-unit (must be in same project) are the same 
public partial class AddressList : ICommonAddress 
{ 
    int id { get; set; } 
    Mode mode { get; set; } 
    Creator creator { get; set; } 
    long[] siteList { get; set; } 
    ATypeClass[] cspList; 

    ICommonAddress CreateAddress() 
    { 
     return new AddressList(); // NOTE: you can even have your ctor private! 
    } 
} 

あなたは次のようにあなたが持っているそれぞれのAddressListタイプのために、あなたは一般的な方法を変更することができ、そして自動的にあなたの共通利用可能なプロパティを示すのIntelliSenseを含め、動作します。また、それを実装することを行う場合。拡張メソッドとして、すべてのAddressListタイプに適用されます(これはpartialを使用するよりも優れています) :

public T ToPrivateAddressList<T>(this ICommonAddress _this) 
    where T: ICommonAddress 
{ 
    T privAddrList = _this.CreateAddress(); 

    // this now works normally, without casting 
    privAddrList.creator = _this.creator; 
    privAddrList.id = _this.id; 
    privAddrList.name = _this.name; 
    privAddrList.mode = _this.mode; 
} 

さて、あなたはこの拡張メソッドへの参照をインポートする場合、あなたが持っている任意の型にToPrivateAddressList()を呼び出すことができます。

A.AddressList a_address = A.AddressList.CreateAddress(); // or new A.AddressList() 
B.AddressList al1 = a_address.ToPrivateAddressList<B.AddressList>(); 
C.AddressList al1 = a_address.AddressList.ToPrivateAddressList<C.AddressList>(); 
+0

ここではどこに行くのか分かりますが、A、B、Cの名前空間(それぞれAddressListクラスが関連付けられています)がWSDLファイルからWeb参照を介してインポートされています。 ..そのため、フィールド、列挙型などはインポート時に自動的に定義されます。私はクラスをgSOAP定義ファイルに定義し、WSDLをビルドしてから現在のアプリケーションにインポートしました。今度は、ワンタイムインポートを行い、次に生成されたファイルを変更することができますが、自動生成されたコードを変更しないことをお勧めします。 – Jon

+0

@ジョン:そうです。そのため、自動生成されたクラスには通常、部分的なクラス定義が含まれており、あなたの質問を考慮すると、私はあなたもそうすると信じています。 1つの部分的な定義がなく、別の部分定義に ':ICommonAddress'が含まれていても、結合されたクラスにインタフェースの実装が含まれていれば問題ありません。それらを別のファイルに配置すると、自動生成されたクラスを手つかずのままにすることができます。 (編集:私はこれを反映する答えを編集)。 – Abel

+0

それはかなり面白そうですね!私はあなたが書いたメソッドのシグネチャに慣れていないので、私はそれらを扱ったことがないので、拡張メソッドを読まなければならないでしょう。明日はさらに調査します! – Jon

0

最後に、私は(私は実際にこれを行うことはできません知っているのに、私は大体としてエレガントなソリューションを探しています)ので、同じようにそれを呼び出す思い描きますあなたは

namespace A 
{ 
    public class MyClass {... } 
} 

やご質問がある

namepsace B 
{ 
    public class MyClass {...} 
} 

を持っている:私は何かを定義することができますどのように "一般的な" THA同じ関数内のtは、時にはA.MyClassとその他のケースB.MyClassを扱うことがあります。

タイプ定義の一部であるのような名前空間について考えると、その話ははっきりしていると思います。 2つの異なるタイプがあり、両方で動作する1つのジェネリックを使用したい場合と同様です。その汎用クラスは、A.MyClassメソッドを選択するときはを、B.MyClassメソッドを選択するときは知っています。

あなたが求めているものでない場合は、明確にしてください。

+0

私の最初の記事を見て、私はそれが何であるかを明確にするためにtrie4dをしました。 – Jon

0

あなたはこれを行うことができる方法を求めている:「新」を言うすることなく、

namespace Old 
{ 
    public New.Address Foo() 
    { 
    New.Address result; 
    //... 
    return result; 
    } 
} 

をAddress?しかし、そうしないと、コードでOld.Addressが使用されますか?

このプロジェクトのビルド/リンク(このコードで)からOld.Addressを削除できますか?

+0

私は最初の投稿でいくつかの追加のノートを作った。 – Jon

関連する問題