I'm trying to query against my Enum based on an attribute on each enum option.
I know how to get the list. That is pretty simple via this code:
var list = Enum.GetValues(typeof(FamilyNameOptions))
.Cast<FamilyNameOptions>()
.Select(v => v.ToString())
.ToList();
If this is my Enum setup, how can I query against the attribute DrawingListIsEnabled where the value is TRUE
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; }
}
The expected result would be a list of 1:
FamilyName1
CodePudding user response:
Rather than using Enum.GetValues
you will need to use reflection to find the static field list;
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
})
Since none of that information will change at runtime, you might wish to create a helper type to cache the results.
CodePudding user response:
Here's a simple LINQ query to accomplish this task:
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);
Note, you don't need your original list
. Also, I'm using the generic version of Enum.GetValues<TEnum>
, which eliminates the need for Cast
in your version.
I kept my LINQ names long in effort to be self-documenting; feel free to go with the typical shorter names. The code works as follows:
Enum.GetValues<FamilyNameOptions>
returns a strongly-typed list of members ofenum FamilyNameOptions
.- first
.Select
statement gets theMemberInfo
objects describing the enum members (along with all custom attributes) - next,
.Where
filters the results based onDrawingListIsEnabledAttribute
'sIsEnabled
property - finally, the last
.Select
grabs the names from theFamilyUserNameAttribute
'sFamilyUserName
property (I presume that's what it's called - change it accordingly if not).