62

[DataContract] を介してクライアント側で利用できるようにするサーバー側クラスがあります。このクラスには、プロパティを通じて利用できるようにしたい読み取り専用フィールドがあります。ただし、get と set の両方を使用せずに [DataMember] プロパティを追加することは許可されていないように見えるため、そうすることができません。

だから - セッターなしで [DataMember] プロパティを持つ方法はありますか?

[DataContract]
class SomeClass
{
    private readonly int _id; 

    public SomeClass() { .. }

    [DataMember]
    public int Id { get { return _id; } }        

    [DataMember]
    public string SomeString { get; set; }
}

または、ソリューションは [DataMember] をフィールドとして使用しますか? (たとえば、ここに示されているように)? これもやってみましたが、フィールドが読み取り専用であることを気にしていないようです..?

編集:このようにハッキングして読み取り専用プロパティを作成する唯一の方法はありますか? (いや、やりたくない…)

[DataMember]
public int Id
{
    get { return _id; }
    private set { /* NOOP */ }
}
4

5 に答える 5

50

あなたの「サーバー側」クラスは、実際にはクライアントに「利用可能」にはなりません。

何が起こるか: データ コントラクトに基づいて、クライアントはサービスの XML スキーマから新しい別のクラスを作成します。サーバー側のクラス自体を使用することはできません!

XML スキーマ定義から新しいクラスを再作成しますが、そのスキーマには、可視性やアクセス修飾子などの .NET 固有のものは含まれていません。結局のところ、それは単なる XML スキーマです。クライアント側クラスは、ネットワーク上で同じ「足跡」を持つように作成されます。たとえば、基本的に同じ XML 形式にシリアル化されます。

クラスに関する .NET 固有のノウハウを標準の SOAP ベースのサービスを介して "転送"することはできません

「SOA の 4 つの原則」(Microsoft の Don Box によって定義されています) を確認してください。

  1. 境界は明示的です
  2. サービスは自律的です
  3. サービスは、クラスではなく、スキーマとコントラクトを共有します
  4. 互換性はポリシーに基づく

ポイント 3 を参照してください - サービスはクラスではなくスキーマとコントラクトを共有します - データ コントラクトのインターフェイスと XML スキーマのみを共有します - それだけです - .NET クラスはありません。

于 2009-12-09T13:21:42.347 に答える
10

プロパティではなくフィールドに DataMember 属性を配置します。

WCF はカプセル化を認識していないことを思い出してください。カプセル化は OOP 用語であり、SOA 用語ではありません。

とはいえ、クラスを使用する人はフィールドが読み取り専用になることに注意してください。サービスを使用する人は誰でも、自分の側のフィールドに完全にアクセスできます。

于 2009-12-09T13:11:06.483 に答える
7

サービス レイヤーのクラスに、Silverlight に渡したいプロパティがいくつかありました。まったく新しいクラスを作成したくありませんでした。

実際には「推奨」ではありませんが、これは、プロパティを Silverlight に渡すTotal(視覚的なデータ バインディングのためだけに) 2 つの悪のうちの小さい方に思えました。

public class PricingSummary
{
    public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area

    public decimal SubTotal { get; set; }
    public decimal? Taxes { get; set; }
    public decimal Discount { get; set; }
    public decimal? ShippingTotal { get; set; }
    public decimal Total
    {
        get
        {
            return + SubTotal
                   + (ShippingTotal ?? 0)
                   + (Taxes ?? 0)
                   - Discount;
        }
        set
        {
            throw new ApplicationException("Cannot be set");
        }
    }
}
于 2010-07-07T05:26:12.107 に答える
-3

クラスを使用してコントラクトを実装する前に、サービス コントラクト (インターフェイス) を定義します。

于 2009-12-09T13:08:05.083 に答える