2011-08-08 10 views
2

各メンバーにDescriptionAttributeの列挙型があります。 私はこのDescriptionAttributeをWCFで送ることができないので(難しい方法を学んだ)、私は説明付きの辞書を私に送るメソッドを作成しようとしています。Enumの説明をWCFでどうにかして "総称的"にする

public IDictionary<Enum, string> GetEnumDescriptionsList(string enumtype) 
{ 
    Type t = Type.GetType(enumtype); 
    if (t.BaseType != typeof(Enum)) 
    { 
     return null; 
    } 

    var returnvalue = new Dictionary<Enum, string>(); 
    foreach (Enum value in Enum.GetValues(t)) 
    { 
     returnvalue.Add(value, value.GetDescription()); 
    } 
    return returnvalue; 
} 

メソッドの呼び出し:: 周りの苦労のビットの後、私は私のWCFサービスでは、このメソッドを作ってみた

var myDict = GetEnumDescriptionsList(typeof (UserType).ToString()); 

を私はその呼び出しを行うとき、これは正常に動作しますメソッドと同じクラスで、私はWCFを介して呼び出しを行うときにnullが返されます。 デバッグ後、私は文字列パラメータが "間違った"値を保持していることを知りました。つまり、クライアント側のUserType.ToString()には、WCFサービスの名前空間とは異なる名前空間があります。

を参照してください。this postはその問題について説明しました。このとき

が、私はここにかなりこだわっている:ジェネリック医薬品はできません、タイプ Typeのパラメータとしてタイプを送ること 一つの最後のオプションは、各列挙型のための方法を書くことで...、( see this post)ことはできません私は(現時点では9)がありますが、それよりも良い方法があるという気持ちがあります。

ありがとうございます。

UPDATE: I辞書を作成するために、コードの一部を以下た@KeithSによって提供されるソリューションの使用:Webサービスに

Assembly asm = Assembly.GetExecutingAssembly();  
foreach (Type type in asm.GetTypes()) 
    { 
     if (type.IsEnum) 
     { 
      enumTypeNames.Add(type.Name, type.AssemblyQualifiedName); 
     } 
    } 

方法は、所与のタイプのすべてのenummember用辞書を返します。

public IDictionary<string, string> GetEnumDescriptionsList(string enumtypename) 
{ 
    var enumtypenames = EnumMethods.GetEnumTypeNames(); 
    var returnvalue = new Dictionary<string, string>(); 

    string fullyQualifiedTypeName; 
    enumtypenames.TryGetValue(enumtypename, out fullyQualifiedTypeName); 

    var enumType = Type.GetType(fullyQualifiedTypeName); 
    foreach (Enum value in Enum.GetValues(enumType)) 
    { 
     returnvalue.Add(value.ToString(), value.GetDescription()); 
    } 
    return returnvalue; 
} 

クライアントからの呼び出し:

var returnvalue = client.GetEnumDescriptionsList(typeof(UserType).Name); 

私は数日前に投稿した問題を除いて、魔法のように動作し、:Name of enum in innerclass changes through WCF-service

のように私は、クライアントからの電話をかける:それは名前を与えます

var returnvalue = client.GetEnumDescriptionsList(typeof(ActionsMailDirectLinkContent).Name); 

ActionsMailDirectLinkContent」戻ってきたがenumtypesの私の辞書には "MailDirectLinkContent"がある。 これを避ける方法がある場合、または私の列挙型をアクションクラスから唯一の解決策として取り出す必要があるかどうか、私の質問です。

更新2: @KeithSが彼のコメントで述べたように、私はクラスからEnumを取り除かなければなりませんでした。私はそれらをサブフォルダに入れて、まだグループ化されていますが、上記の方法はすべてのEnumでこのように動作します。

Thx Keith。

+1

「利用可能なすべての列挙型の列挙型は、」ここに実行可能でしょうか? @Marc; –

+0

;私はそれを示唆すると考えましたが、Enumが追加されたときには、複数の場所でコードを変更する必要があります(したがって、実行する必要があることを知る必要があります)。それが大きな問題であるかどうかは、問題の範囲を超えてさまざまなことに依存します。実際に@KeithS; – KeithS

+0

;それは完全に実行不可能/不適切かもしれません - したがって、コメント(質問)は答えではありません; p –

答えて

3

名前空間でEnum型の名前を一意にする必要がないと安全に考えることができる場合(言い換えると、「MyEnum」という名前の2つのEnumがありません) Dictionary<string,string>を「シンプル」(非修飾)の列挙型の名前に設定し、サーバー側の各列挙型の完全修飾名を含むように設定できます。次に単純なEnum型の名前をメソッドに渡し、ディクショナリで実行して値を取得して返す "実際の"型名を生成し、クライアントとサーバの間の名前空間の違いは問題になりません。

辞書を動的に生成してメンテナンスを必要としないようにすることもできますが、Enum型のアセンブリのスキャンで問題が発生する可能性があります(アセンブリやネームスペースが1つしかない場合に役立ちます) )。

+0

列挙型はすべて同じアセンブリにあります(それらはすべて同じフォルダにあります)。辞書を動的に生成するのは良い考えですが、それを達成するためのヒントはありません(興味深いと思いますが)。あるいは@Marcが彼のコメントで提供した解決策は、より良いものでしょうか? Imhoは、新しい列挙型を追加するときにコードを変更することは、他の誰かがメンテナンスを行い、必要な変更を行うのを忘れてしまったときには良い考えではありません。 – Koen

+0

気になるすべてのEnumが常に1つのプロジェクトとフォルダにある場合(つまり、それらがすべて1つの名前空間にあることを意味する)、さらに簡単になります。名前空間および/またはアセンブリをメソッドにハードコードします。これは、私が答えで作ったものよりもはるかに穏やかな前提ですが、もしあなたのプロジェクトで事がうまくいくならば、このコードに注意を払うためにメモやコメントを書いてください。 – KeithS

+0

あなたが提供したソリューション/アイデアを使って質問を投稿しました。私は列挙型と同じフォルダに静的メソッドを持つ静的クラスを作成しました。 "標準"列挙型でwcf-serviceを呼び出すとうまく動作しますが、クラス内の列挙型で呼び出すと失敗します。どのようにこれを解決するか、または私はクラスからこの列挙型を取らなければならない任意のアイデア? – Koen

3

WCFで説明属性を取得しようとしましたが、まだ取得できませんでした。

私は

[DataContract(Name = "HorseDNAKitRequest.RequestReasonSubType")] 
    public enum RequestReasonSub : byte { 
     [EnumMember(Value = "HERDA")] 
     HERDA = 1, 
     [EnumMember(Value = "HYPP")] 
     HYPP = 2, 
     [EnumMember(Value = "GBED")] 
     GBED = 3, 
     [EnumMember(Value = "OLWS")] 
     OLWS = 4, 
     [EnumMember(Value = "Red Factor And Agouti")] 
     RedFactorandAgouti = 5, 
     [EnumMember(Value = "Red Factor")] 
     RedFactor = 6, 
     [EnumMember(Value = "Agouti")] 
     Agouti = 7, 
     [EnumMember(Value = "Cream")] 
     Cream = 8, 
     [EnumMember(Value = "Pearl")] 
     Pearl = 9, 
     [EnumMember(Value = "Dun")] 
     Dun, 
     [EnumMember(Value = "Silver")] 
     Silver, 
     [EnumMember(Value = "Gray")] 
     Gray, 
     [EnumMember(Value = "Tobiano")] 
     Tobiano, 
     [EnumMember(Value = "Sabino")] 
     Sabino, 
    } 

を次のように使用して、値を取得するための拡張メソッドを使用しています。

public static string GetEnumDescription(this Enum value) 
    { 
     FieldInfo fi = value.GetType().GetField(value.ToString()); 

     EnumMemberAttribute[] attributes = 
      (EnumMemberAttribute[])fi.GetCustomAttributes(
      typeof(EnumMemberAttribute), 
      true); 

     if (attributes != null && attributes.Length > 0) 
      if (attributes[0].Value != null) 
       return attributes[0].Value; 
      else 
       return value.ToString(); 
     else 
      return value.ToString(); 
    } 

それは完全に

0

トリックがあり、契約にこのようにあなたの列挙型を定義作品:

public enum EPaymentCycle : int 
{ 

    [System.Runtime.Serialization.EnumMemberAttribute(Value="Month by Month")] 
    MonthByMonth= 0, 

    [System.Runtime.Serialization.EnumMemberAttribute(Value="Week by Week")] 
    WeekbyWeek= 1, 

    [System.Runtime.Serialization.EnumMemberAttribute(Value="Hour by Hour")] 
    HourbyHour = 2 
} 

public enum EPaymentCycle 
{ 
    [EnumMember(Value = "Month by Month")] 
    Monthly, 

    [EnumMember(Value = "Week by Week")] 
    Weekly, 

    [EnumMember(Value = "Hour by Hour")] 
    Hours 
} 

SvcUtilsのシリアル化が興味深い結果が得られます

EnumMemberAttribute Valueをリフレクションで読み取ることができます。また、予想通りsvcutil直列化によって生成XSDメタデータ・ファイルは次のとおりです。

<xs:simpleType name="EPaymentCycle"> 
<xs:restriction base="xs:string"> 
    <xs:enumeration value="Month by Month" /> 
    <xs:enumeration value="Week by Week" /> 
    <xs:enumeration value="Hour by Hour" /> 
</xs:restriction> 

関連する問題