2011-08-08 31 views
2

我有一個枚舉每個成員DescriptionAttribute。 因爲我無法通過WCF發送這個DescriptionAttribute(我很難學會這一點),所以我一直試圖創建一個方法,向我發送一個描述字典。 有點掙扎左右,我想出了這個方法在我的WCF服務後:獲取枚舉說明以某種方式「一般」通過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; 
} 

的方法的調用:

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

這工作得很好,當我打這通電話在與該方法相同的類中,但是當我通過WCF進行調用時,返回空值。 調試後我發現字符串參數包含一個「不正確的」值。我的意思是,其他客戶端上的UserType.ToString()具有不同的名稱空間,然後是WCF服務中的名稱空間。

閱讀this post解釋了這個問題。

在這一刻我很卡住位置:泛型是不可能的,發送類型爲Type類型的參數是不可能的(see this post),... 最後一個選擇是編寫每個枚舉的方法我有(現在9),但我覺得有一種比這更好的方式。

在此先感謝。

UPDATE: 使用由我具有以下一段代碼來創建字典@KeithS提供的解決方案:

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

在web服務的方法返回每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」。 所以我的問題是如果有一種方法可以避免這種情況,或者我必須將我的枚舉從Actions-class中僅作爲唯一的解決方案。

更新2: 正如在他的評論@KeithS提到的,我不得不採取枚舉了我的班。我已經把它們放在一個子文件夾中,所以它們仍然是「分組」的,但上面的方法對所有的枚舉都是這樣工作的。

Thx Keith。

+1

會的「所有可用的枚舉類型的枚舉」是可行的嗎? –

+0

@Marc;我想提出這個建議,但是當添加一個Enum時,它肯定需要在多個地方更改代碼(因此必須知道你必須這樣做)。這是否是一件大事取決於超出問題範圍的各種事情。 – KeithS

+0

@KeithS確實;它可能是很好的 - 它可能是完全不可行/不合適的 - 因此評論(問題)不是答案; p –

回答

3

如果您可以安全地假定名稱空間不需要使Enum類型的名稱具有唯一性(換句話說,沒有也不會有兩個名爲「MyEnum」的枚舉值得關注),但是,您可以設置一個Dictionary<string,string>鍵入「簡單」(不合格)的枚舉類型名稱,並在服務器端包含每個枚舉類型的完全限定名稱。然後,只需將簡單的Enum類型名稱傳遞給您的方法,然後通過Dictionary運行以產生您獲取並返回值的「真實」類型名稱,並且客戶端和服務器之間的任何名稱空間差異都無關緊要。

字典甚至可以動態生成,因此它需要較少的維護,但是您可能會開始遇到掃描用於Enum類型的程序集的問題(如果只有一個程序集或名稱空間具有您關心的所有枚舉)。

+0

枚舉都位於同一個程序集中(甚至更好:它們都在同一個文件夾中)。也許動態生成字典是一個好主意,但我還沒有弄清楚如何實現它(儘管聽起來很有趣)。或者@Marc在他的評論中提供的解決方案更好嗎? Imho在添加新枚舉時更改代碼並不是一個好主意,因爲其他人必須進行維護並「忘記」進行必要的更改。 – Koen

+0

如果你關心的所有枚舉總是在一個項目和文件夾中(這意味着它們都在一個命名空間中),那麼它會變得更加容易;將命名空間和/或程序集硬編碼到方法中。這是一個比我在答案中作出的更爲令人生厭的假設,但是如果事情在你的項目中工作的方式,那麼可以使用筆記或待辦事項評論來關注此代碼。 – KeithS

+0

我用你提供的解決方案/想法解決了我的問題。我在與Enums相同的文件夾中創建了一個具有靜態方法的靜態類。當我使用「標準」枚舉調用我的wcf服務時它工作正常,但當我使用類內的枚舉進行調用時失敗。任何想法如何解決這個問題,還是我不得不從課堂中拿出這個枚舉? – 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 
{ 
    [EnumMember(Value = "Month by Month")] 
    Monthly, 

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

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

的SvcUtils序列產生一個有趣的結果:

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 
} 

您可以通過反射讀取EnumMemberAttribute的值,然後就可以獲得它。也如預期由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>