2014-02-19 4 views
8

Я следующий ENUM:Enum Описание в строку

[Flags] 
public enum DataFiat { 

    [Description("Público")] 
    Public = 1, 

    [Description("Filiado")] 
    Listed = 2, 

    [Description("Cliente")] 
    Client = 4 

} // DataFiat 

И я создал расширение, чтобы получить атрибут Enum:

public static T GetAttribute<T>(this Enum value) where T : Attribute { 

    T attribute; 
    MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault(); 
    if (info != null) { 
    attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault(); 
    return attribute; 
    } 
    return null; 
} 

Это работает для не Flags Перечисления ... Но когда я есть:

var x = DataFiat.Public | DataFiat.Listed; 
var y = x.GetAttribute<Description>(); 

значение у равно нулю ...

Я хотел бы получить «Público, Filiado, Cliente» ... Как работает ToString().

Как изменить расширение, чтобы сделать эту работу?

Спасибо

+3

[Перерыв флаги вниз в отдельные значения] (http://stackoverflow.com/questions/4171140/iterate-over-values-in-flags-enum), получить атрибут для каждого отдельного значения и построить строку из них всех. –

+0

Но это не сработает, так как ваш метод расширения возвращает только одно значение, однако то, что вы хотите сделать, - это вернуть список значений. В противном случае метод расширения должен обладать знаниями о том, как объединить эти атрибуты. – peter

+1

Это не будет очень удобно локализовать, если вы хотите, чтобы английские колонки использовали его. – Gusdor

ответ

2

Вы можете использовать this:

var values = x.ToString() 
      .Split(new[] { ", " }, StringSplitOptions.None) 
      .Select(v => (DataFiat)Enum.Parse(typeof(DataFiat), v)); 

Чтобы получить отдельные значения. Затем получите значения атрибутов.

Что-то вроде этого:

var y2 = values.GetAttributes<DescriptionAttribute, DataFiat>(); 

public static T[] GetAttributes<T, T2>(this IEnumerable<T2> values) where T : Attribute 
{ 
    List<T> ts =new List<T>(); 

    foreach (T2 value in values) 
    { 
     T attribute; 
     MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault(); 
     if (info != null) 
     { 
      attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault(); 
      ts.Add(attribute); 
     } 
    } 

    return ts.ToArray(); 
} 
+0

Это был вариант ... Но я хотел бы повторить то, что ToString() делает для перечисления Flags ... Он возвращает строки, разделенные запятой –

+0

@MDMoura: добавлен полный рабочий пример. –

+0

@MDMoura: Это вам было полезно? –

0

Я думаю, что вы хотите сделать что-то подобное

using System; 

public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 }; 

public class Example 
{ 
    public static void Main() 
    { 
     int[] values = { -3, -1, 0, 1, 5, Int32.MaxValue }; 
     foreach (var value in values) 
     { 
     ArrivalStatus status; 
     if (Enum.IsDefined(typeof(ArrivalStatus), value)) 
      status = (ArrivalStatus) value; 
     else 
      status = ArrivalStatus.Unknown; 
     Console.WriteLine("Converted {0:N0} to {1}", value, status); 
     } 
    } 
} 
// The example displays the following output: 
//  Converted -3 to Unknown 
//  Converted -1 to Late 
//  Converted 0 to OnTime 
//  Converted 1 to Early 
//  Converted 5 to Unknown 
//  Converted 2,147,483,647 to Unknown 
0
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 

public static class Program 
{ 
[Flags] 
public enum DataFiat 
{ 

    [Description("Público")] 
    Public = 1, 

    [Description("Filiado")] 
    Listed = 2, 

    [Description("Cliente")] 
    Client = 4 

} 

public static ICollection<string> GetAttribute<T>(this Enum value) 
{ 
    var result = new Collection<string>(); 
    var type = typeof(DataFiat); 

    foreach (var value1 in Enum.GetValues(type)) 
    { 
    var memInfo = type.GetMember(value1.ToString()); 
    var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); 
    var description = ((DescriptionAttribute)attributes[0]).Description; 
    result.Add(description); 
    } 

    return result; 
} 

static void Main(string[] args) 
{ 
    var x = DataFiat.Public | DataFiat.Listed; 
    var y = x.GetAttribute<DataFiat>(); 

    var output = string.Join(" ", y.ToArray()); 
    Console.WriteLine(output); 
} 
} 

Я изменил T к ICollection, но вы можете изменить его, как вы хотите или вы можете merege данных в методе и вернуть строку обратно.

-1

Я придумал другое решение, основанное на моем предыдущем коде. Он может быть использован следующим образом:

DataFiat fiat = DataFiat.Public | DataFiat.Listed; 
    var b = fiat.ToString(); 
    var c = fiat.GetAttributes<TextAttribute>(); 

    var d = fiat.GetAttributes<TextAttribute, String>(x => String.Join(",", x.Select(y => y.Value))); 

Я думаю, что это будет легко использовать или получить атрибуты или делать что-то с ними.

Как вы думаете?

Сообщите мне, если код может быть как-то улучшен. Вот код:

public static List<T> GetAttributes<T>(this Enum value) where T : Attribute { 

    List<T> attributes = new List<T>(); 

    IEnumerable<Enum> flags = Enum.GetValues(value.GetType()).Cast<Enum>().Where(value.HasFlag); 

    if (flags != null) { 

    foreach (Enum flag in flags) { 
     MemberInfo info = flag.GetType().GetMember(flag.ToString()).FirstOrDefault(); 
     if (info != null) 
     attributes.Add((T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault());   
    } 

    return attributes; 

    } 

    return null; 

} // GetAttributes 

public static Expected GetAttributes<T, Expected>(this Enum value, Func<List<T>, Expected> expression) where T : Attribute { 

    List<T> attributes = value.GetAttributes<T>(); 

    if (attributes == null) 
    return default(Expected); 

    return expression(attributes); 

} // GetAttributes 
Смежные вопросы