gpt4 book ai didi

c# - 构建、迭代和调用不同类型的表达式列表

转载 作者:太空宇宙 更新时间:2023-11-03 14:59:06 24 4
gpt4 key购买 nike

考虑以下定义:

public class AlternateDescriptionAttribute : Attribute
{
public string AlternateDescription { get; }

public AlternateDescriptionAttribute(string s)
{
AlternateDescription = s;
}
}

enum Metasyntactic
{
[AlternateDescription("Corge")]
Foo,

[AlternateDescription("Quux")]
[Description("Qux")]
Bar,

Baz,
}

我想按优先顺序获取这些枚举的属性值,即AlternateDescription > Description > enum.ToString()。换句话说,如果有 AlternateDescription,则使用 AlternateDescription,如果不存在,则回退到 Description,如果两者都不存在,则回退到 ToString。

为此,我创建了以下辅助方法:

public static bool TryGetAttributeValue<TAttribute, T>(Enum field, Expression<Func<TAttribute, T>> valueExpression, out T value)
where TAttribute : Attribute
{
var attribute = TryGetAttribute<TAttribute>(field);
if (attribute == null)
{
value = default(T);

return false;
}

value = valueExpression.Compile()(attribute);

return true;
}

像这样使用:

static string GetNiceDescription(Enum field)
{
if (TryGetAttributeValue<AlternateDescription, string>(field, a => a.AlternateDescription, out string alternateDesc))
{
return alternateDesc;
}

if (TryGetAttributeValue<DescriptionAttribute, string>(field, a => a.Description, out string description))
{
return description;
}

return field.ToString();
}

然而,这有点笨拙,特别是因为我有超过 2 个我感兴趣的属性,并且将来可能会更多。我想要做的是能够将属性及其关联的表达式放入一个列表中,然后对其进行迭代 - 到目前为止,我已经想出了以下内容:

static string GetNiceDescriptionViaExpressions(Enum field)
{
Expression<Func<AlternateDescriptionAttribute, string>> exp1 = a => a.AlternateDescription;
Expression<Func<DescriptionAttribute, string>> exp2 = a => a.Description;
var expressions = new LambdaExpression[] { exp1, exp2, };

foreach (var exp in expressions)
{
var attributeType = exp.Parameters[0].Type;
var attributeInstance = field.GetType().GetField(field.ToString()).GetCustomAttributes(attributeType, false).FirstOrDefault();
if (attributeInstance == null)
{
continue;
}

var result = exp.Compile().DynamicInvoke(attributeInstance);
if (result != null)
{
return (string)result;
}
}

return field.ToString();
}

但这并不优雅,而且在编译时也不是特别安全,如果可以编写如下内容,我会更愿意:

static string GetNiceDescriptionViaExpressions(Enum field)
{
// attributeExpressionsDictionary would be a dictionary mapping
// attribute types to expressions - not sure how that would look...
foreach (var attribute in attributeExpressionsDictionary)
{
if (TryGetAttributeValue<attribute.Key, string>(field, attribute.Value, out description))
{
return description;
}
}

return field.ToString();
}

这可能吗?如果不是,可以对 GetNiceDescriptionViaExpressions 进行哪些改进以使其更安全和/或更高效?

最佳答案

您是否考虑过使用具有 Weight 属性的单个属性定义和 enum 字段的多个注释?

让单个属性负责您的描述要容易得多。

属性定义:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
public sealed class DescriptionAttribute : Attribute
{
public DescriptionAttribute(int weight, string value)
{
this.Weight = weight;
this.Value = value;
}

public int Weight { get; }
public String Value { get; }
}

Weight 属性将用作要使用的描述的决胜局。

下面是如何使用注释枚举:

public enum SomeEnum
{
[Description(1, "Official description"),
Description(2, "Alternate Description")]
Val1,

[Description(1, "Description")]
Val2,

Val3

GetDescription 方法的实现:

public static String GetDescription<TEnum>(TEnum @enum) where TEnum: struct
{
var description = typeof(TEnum)
.GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
.Single(x => EqualityComparer<TEnum>.Default.Equals((TEnum)x.GetValue(null), @enum))
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)
.OfType<DescriptionAttribute>()
.OrderBy(x => x.Weight)
.Select(x => x.Value)
.DefaultIfEmpty(@enum.ToString())
.First();

return description;
}

注意:我使用的是通用版本以避免装箱枚举值。在当前版本中,该方法可以与任何结构一起使用,这是 Not Acceptable 。我的建议是使用运行时检查传递的值是否为实际枚举以避免将来出现问题。

这里是简单的用法:

// Official description
var fDescription = GetDescription(SomeEnum.Val1);

// Description
var sDescription = GetDescription(SomeEnum.Val2);

// Val3
var tDescription = GetDescription(SomeEnum.Val3);

关于c# - 构建、迭代和调用不同类型的表达式列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47199570/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com