【发布时间】:2014-04-09 10:22:44
【问题描述】:
参考下面的 2 个类,我经常写这样的 LINQ 语句..
using (var db = new DBContext())
{
var result = db.Countries
.Select(c => new
{
c.Name,
c.Leader != null ? c.Leader.Title : String.Empty,
c.Leader != null ? c.Leader.Firstname : String.Empty,
c.Leader != null ? c.Leader.Lastname : String.Empty
});
}
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
public Leader Leader { get; set; }
}
public class Leader
{
public string Title { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
我的问题是我必须不断重复对子导航属性的 null 检查,我想知道是否有一种方法可以使用某种表达式树来动态提取属性值,同时检查 null 值以及它们是否不存在发回一个空字符串,类似于下面的方法..
public class Country
{
// Properties //
public string SafeGet(Expression<Func<Country, string>> fnc)
{
// Unpack fnc and check for null on each property?????
}
}
用法:
using (var db = new DBContext())
{
var result = db.Countries
.Select(c => new
{
c.Name,
c.SafeGet(l => l.Leader.Title),
c.SafeGet(l => l.Leader.Firstname),
c.SafeGet(l => l.Leader.Lastname)
});
}
如果有人能提供一个很好的基本示例,因为除了创建表达式树之外,我对表达式树没有太多经验。
谢谢。
更新 -> 会像下面这样工作吗?
public string GetSafe(Expression<Func<Country, string>> fnc)
{
var result = fnc.Compile().Invoke(this);
return result ?? string.Empty;
}
【问题讨论】:
-
坦率地说,这是可行的,但会带来太多麻烦而收效甚微(几乎可以肯定,您只需要支持特定的构造,否则您会做更多的工作而没有实际利益)。您建议的解决方案不起作用。
-
看来您可以通过首先使用
var defaultLeader = new Leader { Title = "", Firstname = "" }创建一个具有空属性的领导者然后使用空合并(c.Leader ?? defaultLeader).Title来实现更简洁的效果。额外奖励:也适用于所有其他属性类型。 -
@Jon - 我在想我可以将 GetSafe 方法放在一个基本泛型类中,以供许多其他类使用。此外,在我的示例中,我只是使用 Leader 属性但是在实践中可能有多达 5 或 6 个不同的属性。我想这意味着我必须为您提出的解决方案创建那么多 defaultProperties?
-
是的,你需要很多。
-
看看 NullSafe here。但是当你向下更深时它真的很有帮助,在这里它实际上不会为你节省很多打字时间。
标签: c# linq expression lambda