web-dev-qa-db-ja.com

WCF Webサービスで列挙型を使用していますか?

いくつかの値が割り当てられている場合、または列挙型が フラグ 属性。また、列挙型を公開するWebサービスは維持するのが難しいが、実際に実行可能な議論を提供することはできなかったとも述べた。あなたの経験から、WCF Webサービスで列挙型を使用することの長所と短所は何ですか?

41
Darin Dimitrov

人々がウェブサービスで列挙型を避けることを推奨する理由は、それらが微妙な後方互換性の問題を作成するためです。

同じことが通常の列挙型にも当てはまりますが、Webサービスでは、特に.NETで生成されたプロキシ(以下を参照)で問題がさらに明確になります。

  • 列挙が入力のみの場合、問題はありません。
  • Enumerateをoutパラメータにできる場合、新しい要素を追加してそれを返すと、古いクライアントに問題が発生する可能性があります。
    • クライアントが.NETで生成されたプロキシを使用している場合、呼び出し側がそれを処理する前に(逆シリアル化で)ブレークします。
    • プロキシ用に生成されたコードが変更をサポートしていても(たとえば、列挙を文字列にマップする場合)、クライアントのユーザーコードが新しい予期しない値を適切に処理しない可能性があります(決して実行されないパスになる可能性があります)

パラメータを文字列として定義することにより、APIのユーザーに値が将来変更される可能性があることを知らせます。価値は決して変わらないと思っていても、準備をしておくのは良い習慣です。

このトピックについては、Dare Obasanjoによる good post があります。

41
MMind

私はWCFで列挙型を使用しており、相互運用性のシナリオでも使用しています。サービスの両側を制御すると、作業がしやすくなります。サービスの片側のみを制御する場合は、言及した問題に注意する必要があります。

列挙型は文字列変数よりもはるかに優れているため、他に何を使用するかを選択できます。 enumの代わりに文字列を使用することは、SOAでは「loosey Goosey」と呼ばれるアンチパターンです。

18
khebbie

列挙型は、WSDLおよびXSDでxsd:enumerationスキーマ要素を介して完全にサポートされています。単一の値とフラグスタイルの列挙の両方をサポートします。フラグ列挙の複数の値はスペースで区切られます。

したがって、標準に準拠したプラットフォームで列挙を使用しても問題はありません。

10
Greg Beech

もちろん、それはすべて、このWCFサービスをどこで使用するかによって異なります。

それを使用する単一のアプリケーションの場合、コントラクトを変更しても効果はありません。

複数の内部アプリケーションの場合、コントラクトを変更すると、他のアプリケーションでいくつかの変更が必要になる場合があります。

そして最後に、WCFサービスがパブリックの場合、異なるバージョンのサービスの2つのバージョンを提供して、それらを使用するユーザーがクライアントのバージョンを新しいサービスに転送できるようにする必要があります。

それはすべてあなたのニーズに正直依存しています。

3
Maxime Rouiller

WSDLの列挙型は、メンテナンスの問題と見なす必要があります。

列挙値の追加または削除は、インターフェイスのメジャーアップデートのトリガーです(そうする必要があります!)。列挙型が出力値である場合、現在のクライアントが確立された契約を破らないようにするために、新しいURIを通じてWSDLの新しいバージョンを定義する必要があります(「これらの新しい予期しない値を受け取った場合、 ? ")enumが入力値である場合、これをマイナーアップデートと見なすことができます(「現在のクライアントはこの新しい値について知る必要がないため」)。しかし、これらのクライアントがこの新しいオプション/機能の追加(理由のためにこの新しい列挙値を追加しましたよね?)は、遅かれ早かれ、新しいバージョンのインターフェースに切り替えるように依頼することになります。

そして、これは列挙型の機能的な意味とは関係がないと思います。

ベストプラクティスの側に留まれば、安全です。

2
Zackatoustra

Enum以外を使用しても互換性の問題は解決されず、非表示になるだけです。 entを置き換えるためにintを使用するとします。クライアントランタイムが不明な値に達するまで、互換性の問題を本当に解決しましたか、それとも偽装しましたか?

ただし、言及する価値があることは1つあります。WCFプロキシは、明示的に設定された列挙型数値を再作成しません。列挙型が「穴」で宣言されている場合、

enum ErrorCodes
{
  OK = 0,
  GenericError = 100,
  SomeOtherError = 101,
}

クライアント側の表現はこのようになります

enum ErrorCodes
{
  OK,
  GenericError,
  SomeOtherError,
}

...クライアントでは、(int)ErrorCodes.GenericErrorが1になります。

構文の等価性はありますが、数値の等価性はありません。

2
BalintN

私はWCFベースのサービスで列挙型を問題なく使用しました。あなたが言及する可能性のある問題は間違いなく考慮すべきことですが、かなり静的な状況で列挙型を適用することを確認すれば、おそらくそれほど問題はありません。

1
Kwal

実世界のストーリー(匿名のために値が変更されました)。アプリケーションで暗黙のenumを使用するために使用します

public enum { orange, banana, mango }

順序と新しい値に関するリファクタリングをいくつか行い、それを明示的にすることにします。

public enum { orange=1, banana=2, grape=3, mango=4 }

不快に見えません...
次に、ウェブサイトが爆発します。スクラッチヘッド、サービスのチェック、デバッグメッセージの追加など、すべて問題ないようです。
ウサギの穴を1日後、理由は、列挙型を戻り値の型として使用していた基本のwcfサービスです。

見たところ、Wcfはdefault値のない列挙型を好みません。

修正:

public enum { wcfBugBane=0, orange=1, banana=2, grape=3, mango=4 }

だから...それはあなたを噛むかもしれません。

0
Noctis

ここにアプローチがあります。多分それは面倒です。列挙型を使用できないのは本当に嫌いです。

認識されない値の逆シリアル化を適切に処理し、代わりにデフォルト値を返します。デフォルト値は安全である必要があります-許容可能なフォールバック、またはアプリケーションが例外として認識できるもの。 (「未指定」のように。)

拡張機能により、比較する前にnullチェックを行う必要がなくなります。

[DataContract]
public class EnumValue<T> where T : struct
{
    [DataMember]
    private string _raw = string.Empty;

    [IgnoreDataMember]
    private bool _parsed;

    [IgnoreDataMember]
    private T _parsedValue;

    public EnumValue()
    {
        Set(default(T));
    }

    public EnumValue(T value)
    {
        Set(value);
    }

    internal T Value
    {
        get
        {
            if (_parsed) return _parsedValue;
            if (!Enum.TryParse<T>(_raw, out _parsedValue))
            {
                _parsedValue = default(T);
            }
            _parsed = true;
            return _parsedValue;
        }
    }

    public void Set(T value)
    {
        _raw = value.ToString();
        _parsedValue = value;
        _parsed = true;
    }
}

public static class EnumValueExtensions
{
    public static T GetValue<T>(this EnumValue<T> enumValue) where T : struct
    {
        return enumValue == null ? default(T) : enumValue.Value;
    }

    public static bool EqualsValue<T>(this EnumValue<T> enumValue, T compareTo) where T : struct
    {
        return (enumValue.GetValue().Equals(compareTo));
    }
}
0
Scott Hannen