3

外部 WSDL ファイルから svcutil によって生成された類似のクラスが多数あります。どのクラスにも、という名前のHeaderプロパティとプロパティがあります。stringclass name + "1"

たとえば、プロパティとプロパティSimpleRequestを持つクラスがあります。 もう1つは、プロパティとプロパティを持っていることです。HeaderSimpleRequest1
ComplexRequestHeaderComplexRequest1

そのため、そのようなクラスに共通のインターフェースを作成したいと考えています。したがって、基本的には次のように定義できます。

interface ISomeRequestClass {
  string Header;
  // here is some definition for `class name + "1"` properties...
}

インターフェイスでそのようなメンバーを定義することは可能ですか?


これが投稿編集です...

生成されたクラスのサンプルは次のとおりです。

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class SimpleRequest
{


    public string Header;

    [System.ServiceModel.MessageBodyMemberAttribute(Name="SimpleRequest", Namespace="data", Order=0)]
    public SimpleRequestMsg SimpleRequest1;

    public SimpleRequest()
    {
    }

    public SimpleRequest(string Header, SimpleRequestMsg SimpleRequest1)
    {
        this.Header = Header;
        this.SimpleRequest1 = SimpleRequest1;
    }
}

編集後 2

この厄介な +1 プロパティの定義を実際の実際の画像を表すように変更しました。それはすべて異なるクラスタイプを持っています。では、どうすればそれを共通インターフェイスに引き出すことができますか?


編集後 3

これは、より明確にすることができる結合された質問です。

4

5 に答える 5

3

インターフェイスをより一般的に定義できます。

interface ISomeRequestClass {
  string HeaderProp {get; set;}
  string Prop {get; set;}
}

また、次のようにインターフェイスメンバーをクラスフィールドにマッピングすることで、具体的なクラスを(追加のコードファイルで)拡張できます。

public partial class SimpleRequest : ISomeRequestClass
{
  public string HeaderProp
  {
    get
    {
      return Header;
    }
    set
    {
      Header = value;
    }
  }

  public string Prop
  {
    get
    {
      return SimpleRequest1;
    }
    set
    {
      SimpleRequest1= value;
    }
  }
}
于 2012-05-03T22:17:38.510 に答える
3

編集(コードサンプルを見た後):技術的に言えば、コードにはHeader プロパティがなく、Header フィールドがあります。インターフェイスではフィールドを指定できないため、これは重要な違いです。ただし、以下で説明する方法を使用すると、フィールド値を返すプロパティをクラスに追加できます。


インターフェイスでそのようなメンバーを定義することは可能ですか?

いいえ、インターフェイス名を動的にすることはできません。とにかく、そのようなインターフェースはあまり役に立ちません。class のインスタンスがある場合、ISomeRequestClassそのプロパティにアクセスするためにどの名前を使用しますか?

ただし、明示的なインターフェイスの実装を使用できます。

interface ISomeRequestClass {
    string Header { get; set; }
    string ClassName1 { get; set; }
}

class SomeClass : ISomeRequestClass {
     string Header { ... }

     string SomeClass1 { ... }

     // new: explicit interface implementation
     string ISomeRequestClass.ClassName1 {
          get { return SomeClass1; }
          set { SomeClass1 = value; }
     }
}
于 2012-04-26T08:34:17.907 に答える
2

クラスとプロパティの命名については、しばらく脇に置いておきます。

特定の +1 タイプに関連するプロパティを持つインターフェイスを作成する場合は、いくつかのオプションがあります。

+1 に基本クラスを使用する

+1 クラスの両方が同じ基本クラスから継承する場合、これをインターフェイス定義で使用できます。

public interface IFoo
{
 [...]
 PlusOneBaseType MyPlusOneObject{get;set;}
}

インターフェイスにジェネリック プロパティを作成する

このメソッドを使用すると、+1 プロパティの型をジェネリック パラメーターとして指定できます。

public interface IFoo<TPlusOneType>
{
 [...]
 TPlusOneType MyPlusOneObject{get;set;}
}

次のように使用できます。

public class SimpleRequest : IFoo<SimpleRequest1>
{
 [...]
}

アップデート

クラスが部分クラスであることを考えると、インターフェイスを実装する部分クラスの 2 番目の (マシン生成ではない) バージョンをいつでも作成できます。

于 2012-04-26T08:36:05.107 に答える
2

あなたはsvcutilについて言及したので、これらのクラスをWCF DataContractsとして使用していると思いますか?

その場合は、のnameプロパティを使用できますDataMemberAttribute

interface IRequest 
{
    string Header { get; set; }
    string Request1 { get; set; }
}

[DataContract]
class SimpleRequest : IRequest
{
    [DataMember]
    public string Header { get; set; }

    [DataMember(Name="SimpleRequest1"]
    public string Request1 { get; set; }
}

[DataContract]
class ComplexRequest : IRequest
{
    [DataMember]
    public string Header { get; set; }

    [DataMember(Name="ComplexRequest1"]
    public string Request1 { get; set; }
}

将来、コードを再生成するときに、さらに多くの作業を行うことが懸念される場合は、この変換を自動的に行う PowerShell スクリプトを作成することをお勧めします。結局、svcutil は Microsoft のある人によって書かれた単なるスクリプトです。それは魔法でも「正しい」でも「標準」でもありません。スクリプトで scvutil を呼び出し、結果のファイルに簡単な変更を加えることができます。

 

編集(あなたの編集を見た後)

MessageBodyMemberAttributeNameプロパティを既に使用しているため、これを変更するだけです。

public string SimpleRequest1; 

public string Request1; 
于 2012-04-26T08:57:00.243 に答える
0

共通のインターフェースを持つために、これらのクラスが実際に必要ですか?代わりに、リフレクションを使用して問題のフィールドにアクセスできるラッパーインターフェイス(または単なる具象クラス)を作成したいと思います。

// TODO: Make this class implement an appropriate new interface if you want
// to, for mocking purposes.
public sealed class RequestWrapper<TRequest, TMessage>
{
    private static readonly FieldInfo headerField;
    private static readonly FieldInfo messageField;

    static RequestWrapper()
    {
        // TODO: Validation
        headerField = typeof(TRequest).GetField("Header");
        messageField = typeof(TRequest).GetField(typeof(TRequest).Name + "1");
    }

    private readonly TRequest;

    public RequestWrapper(TRequest request)
    {
        this.request = request;
    }

    public string Header
    {
        get { return (string) headerField.GetValue(request); }
        set { headerField.SetValue(request, value); }
    }

    public TMessage Message
    {
        get { return (TMessage) messageField.GetValue(request); }
        get { messageField.SetValue(request, value); }
    }
}

リフレクションが遅すぎることが判明した場合は、式ツリーを使用してこのデリゲートを作成できますが、最初は単純なソリューションに固執します。

これの利点は、このコードを1回だけ記述する必要があることです。ただし、実際の要求オブジェクトのラッパーを作成することを意味しますが、部分的なクラスの回答では行われません。

于 2012-05-09T05:55:12.037 に答える