基于属性对枚举执行 LINQ 操作
Perform LINQ operations on an Enum based on Attributes
我正在尝试根据每个枚举选项的属性查询我的枚举。
我知道如何获取列表。通过这段代码非常简单:
var list = Enum.GetValues(typeof(FamilyNameOptions))
.Cast<FamilyNameOptions>()
.Select(v => v.ToString())
.ToList();
如果这是我的 Enum 设置,我如何查询值为 TRUE
的属性 DrawingListIsEnabled
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; }
}
预期结果将是列表 1:
FamilyName1
而不是使用 Enum.GetValues
您将需要使用反射来查找静态字段列表;
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
})
由于 none 该信息会在运行时发生变化,您可能希望创建一个辅助类型来缓存结果。
这是完成此任务的简单 LINQ 查询:
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);
请注意,您不需要原件 list
。另外,我使用的是 Enum.GetValues<TEnum>
的通用版本,这样您的版本就不需要 Cast
。
为了成为 self-documenting,我一直保留我的 LINQ 名称;随意使用典型的较短名称。代码工作如下:
Enum.GetValues<FamilyNameOptions>
returns enum FamilyNameOptions
. 的 strongly-typed 成员列表
- 第一个
.Select
语句获取描述枚举成员的 MemberInfo
个对象(以及所有自定义属性)
- 接下来,
.Where
根据 DrawingListIsEnabledAttribute
的 IsEnabled
属性 过滤结果
- 最后,最后一个
.Select
从 FamilyUserNameAttribute
的 FamilyUserName
属性 中获取名称(我想这就是它的名字 - 如果不是,请相应地更改它) .
我正在尝试根据每个枚举选项的属性查询我的枚举。
我知道如何获取列表。通过这段代码非常简单:
var list = Enum.GetValues(typeof(FamilyNameOptions))
.Cast<FamilyNameOptions>()
.Select(v => v.ToString())
.ToList();
如果这是我的 Enum 设置,我如何查询值为 TRUE
的属性 DrawingListIsEnabled 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; }
}
预期结果将是列表 1:
FamilyName1
而不是使用 Enum.GetValues
您将需要使用反射来查找静态字段列表;
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
})
由于 none 该信息会在运行时发生变化,您可能希望创建一个辅助类型来缓存结果。
这是完成此任务的简单 LINQ 查询:
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);
请注意,您不需要原件 list
。另外,我使用的是 Enum.GetValues<TEnum>
的通用版本,这样您的版本就不需要 Cast
。
为了成为 self-documenting,我一直保留我的 LINQ 名称;随意使用典型的较短名称。代码工作如下:
Enum.GetValues<FamilyNameOptions>
returnsenum FamilyNameOptions
. 的 strongly-typed 成员列表
- 第一个
.Select
语句获取描述枚举成员的MemberInfo
个对象(以及所有自定义属性) - 接下来,
.Where
根据DrawingListIsEnabledAttribute
的IsEnabled
属性 过滤结果
- 最后,最后一个
.Select
从FamilyUserNameAttribute
的FamilyUserName
属性 中获取名称(我想这就是它的名字 - 如果不是,请相应地更改它) .