Estoy tratando de consultar mi Enum en función de un atributo en cada opción de enumeración.
Sé cómo conseguir la lista. Eso es bastante simple a través de este código:
var list = Enum.GetValues(typeof(FamilyNameOptions)) .Cast<FamilyNameOptions>() .Select(v => v.ToString()) .ToList();
Si esta es mi configuración de Enum, ¿cómo puedo consultar el atributo DrawingListIsEnabled donde el valor es VERDADERO ?
public enum FamilyNameOptions { [DrawingListIsEnabled(true)] [FamilyUserName("FamilyName1")] FamilyName1= 0, [DrawingListIsEnabled(false)] [FamilyUserName("FamilyName2")] FamilyName2= 1, } /// <summary> /// DrawingListIsEnabledAttribute /// </summary> /// <seealso cref="System.Attribute" /> [AttributeUsage(AttributeTargets.All)] public class DrawingListIsEnabledAttribute : Attribute { /// <summary> /// Initializes a new instance of the <see cref="DrawingListIsEnabledAttribute"/> class. /// </summary> /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param> public DrawingListIsEnabledAttribute(bool isEnabled) { this.IsEnabled = isEnabled; } /// <summary> /// Gets a value indicating whether this instance is enabled. /// </summary> /// <value> /// <c>true</c> if this instance is enabled; otherwise, <c>false</c>. /// </value> public bool IsEnabled { get; private set; } }
El resultado esperado sería una lista de 1:
Nombre de familia1
En lugar de usar Enum.GetValues
, deberá usar la reflexión para encontrar la lista de campos estáticos;
typeof(FamilyNameOptions) .GetFields(BindingFlags.Static | BindingFlags.Public) // For definition order, rather than value order; .OrderBy(f => f.MetadataToken) .Select(f => new { Value = (FamilyNameOptions)f.GetValue(null), Text = f.Name, Enabled = f.GetCustomAttribute<DrawingListIsEnabledAttribute>()?.IsEnabled ?? false, FamilyName = f.GetCustomAttribute<FamilyUserNameAttribute>()?.Name })
Dado que ninguna de esa información cambiará en el tiempo de ejecución, es posible que desee crear un tipo auxiliar para almacenar en caché los resultados.
Aquí hay una consulta LINQ simple para realizar esta tarea:
var items = Enum.GetValues<FamilyNameOptions>() .Select(item => item.GetType().GetMember(item.ToString()).FirstOrDefault()) .Where(memberInfo => memberInfo?.GetCustomAttribute<DrawingListIsEnabledAttribute>().IsEnabled ?? false) .Select(enabledMemberInfo => enabledMemberInfo.GetCustomAttribute<FamilyUserNameAttribute>().FamilyUserName);
Tenga en cuenta que no necesita su list
original. Además, estoy usando la versión genérica de Enum.GetValues<TEnum>
, que elimina la necesidad de Cast
en su versión.
Mantuve mis nombres de LINQ largos en un esfuerzo por documentarme a mí mismo; siéntase libre de ir con los típicos nombres más cortos. El código funciona de la siguiente manera:
Enum.GetValues<FamilyNameOptions>
devuelve una lista fuertemente tipada de miembros de enum FamilyNameOptions
..Select
obtiene los objetos MemberInfo
que describen los miembros de la enumeración (junto con todos los atributos personalizados).Where
filtra los resultados en función de la propiedad DrawingListIsEnabledAttribute
de IsEnabled
.Select
toma los nombres de la propiedad FamilyUserNameAttribute
de FamilyUserName
(supongo que así es como se llama; cámbielo en consecuencia si no).