[英]Centralize ternary logic in EF6/LINQ
I seem to often (when dealing with enums) do things like this: 我似乎经常(在处理枚举时)执行以下操作:
.Select(x => new {
enumDesc = (
x.status == GoodStatus ? "Good!"
: x.status == BadStatus ? "Bad<angryface>"
: x.status == Unknown ? "no clue"
)
})
or 要么
let enumDesc = (
x.status == GoodStatus ? "Good!"
: x.status == BadStatus ? "Bad<angryface>"
: x.status == Unknown ? "no clue"
)
Some queries end up having dozens of these conditions, like a project I'm working on now. 有些查询最终会遇到许多这样的情况,例如我现在正在处理的项目。 Doing it this way is nice because it can be translated into a SQL case statement so it's faster than iterating through after materialization.
这样做很不错,因为它可以转换为SQL case语句,因此比在实现之后进行迭代要快。 In my current project, however, I need to do this in more than one place/query.
但是,在我当前的项目中,我需要在多个位置/查询中执行此操作。 Is there any way to do this in a performant and reusable way (ie, translates to SQL) without refactoring the structures (eg moving the enum into a table)?
有什么方法可以执行且可重用(即转换为SQL)而不重构结构(例如,将枚举移动到表中)吗? I haven't been able to come up with one.
我还没办法提出。 If I could capture or alias just the ternary stuff, that would be good enough, or making an expression that "selects" from constants or attributes or something...
如果我可以仅捕获或别名三元数据,那就足够了,或者创建一个从常量或属性或其他东西中“选择”的表达式...
If you're open to avoiding if
logic, consider the following: 如果您愿意避免使用
if
逻辑,请考虑以下事项:
There are often times where I see developers in C# lean towards using the DescriptionAttribute
and combining that with an extension method to lookup the enum
values' description value. 我经常看到C#中的开发人员倾向于使用
DescriptionAttribute
并将其与扩展方法结合起来以查找enum
值的描述值。
public enum Status
{
[Description("no clue")]
Unknown,
[Description("Good!")]
Good,
[Description("Bad<angryface>")]
Bad
}
public static class EnumExt
{
public static string Description<T>(this T source)where T : struct, IConvertible
{
if (!typeof (T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
var fi = source.GetType().GetField(source.ToString());
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : source.ToString();
}
}
Here's a working .NET Fiddle I threw together quick to demonstrate this. 这是一个有效的.NET小提琴,我迅速地进行了演示。
Otherwise, if you want to map a string to an enum
value without the usage of attributes -- I'd suggest a switch
instead... 否则,如果要在不使用属性的情况下将字符串映射到
enum
值,则建议switch
...
You can use a method that implements an Expression<Func<T, T2>>
, see example below: 您可以使用实现
Expression<Func<T, T2>>
,请参见下面的示例:
public enum Status
{
GoodStatus,
BadStatus,
Unknown
}
public class foo
{
public Status status;
}
public void Execute()
{
List<foo> list = new List<foo>
{
new foo
{
status = Status.BadStatus
},
new foo
{
status = Status.GoodStatus
},
new foo
{
status = Status.GoodStatus
},
new foo
{
status = Status.Unknown
}
};
var descStatus = list.Select(GetStatus).ToList();
}
public Expression<Func<foo, object>> GetStatus(foo _foo)
{
return x => new
{
enumDesc = _foo.status == Status.GoodStatus
? "Good!"
: _foo.status == Status.BadStatus
? "Bad<angryface>"
: _foo.status == Status.Unknown ? "no clue" : ""
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.