I have a static class with constants that I want to store in a list to be used in a DropDown
public static class DateFormatConstant
{
[Display(Name = "DD/MM/YYYY")]
public const string DayMonthYear = "dd/MM/yyyy";
[Display(Name = "MM/DD/YYYY")]
public const string MonthDayYear = "MM/dd/yyyy";
[Display(Name = "YYYY/MM/DD")]
public const string YearMonthDay = "yyyy/MM/dd";
[Display(Name = "MM/DD/YY")]
public const string MonthDayTwoDigitYear = "MM/dd/yy";
}
Is there a way to get them into a List<SelectListItem>
?
The answer from @maembe utilizing Reflection is a good way to go. But since you already are decorating your constants with the Display
attribute I'll expand this solution to use the attribute. Note that I use LINQ's Query Syntax here as opposed to the Method Syntax in the other answer.
Here's my code:
var selectLisItems =
from f in typeof(DateFormatConstant).GetFields(BindingFlags.Public | BindingFlags.Static)
where f.IsLiteral && f.FieldType == typeof(string)
from a in f.CustomAttributes
where a.AttributeType == typeof(DisplayAttribute)
let na = a.NamedArguments.First(x => x.MemberName == nameof(DisplayAttribute.Name))
select new SelectListItem
{
Text = (string)na.TypedValue.Value,
Value = (string)f.GetRawConstantValue()
};
var list = selectLisItems.ToList();
What does it actually do? Let's look at the parts of the query.
from f in typeof(DateFormatConstant).GetFields(BindingFlags.Public | BindingFlags.Static)
where f.IsLiteral && f.FieldType == typeof(string)
Here I'm selecting all constants from the DateFormatConstant
class that are of type string
.
from a in f.CustomAttributes
where a.AttributeType == typeof(DisplayAttribute)
Now I'm limiting to constants that actually have the Display
attribute. Note that the "real" type here is DisplayAttribute
let na = a.NamedArguments.First(x => x.MemberName == nameof(DisplayAttribute.Name))
Next is going through the arguments of the attribute and search for Name
. I can safely use First
here because I already limited to the DisplayAttribute
type and know therefore that it has a Name
property.
select new SelectListItem
{
Text = (string)na.TypedValue.Value,
Value = (string)f.GetRawConstantValue()
};
var list = selectLisItems.ToList();
At last I'm constructing SelectListItem
from the attribute and the fields and create the desired List<SelectListItem>
from the query.
Note: All this assumes that you want all string constants from your class to be contained in the list. If your class contains more constants that should go in different lists you can use the GroupName
property of the Display
attribute to group constants together. I'll leave it as an excercise to expand the code accordingly.