[英]How to build a properties selector?
我试图使用以下格式进行更新 function:
public int Update(
Item Item,
Expression<Func<Item, object>> selector)
如何读取选择器中选择的属性? 我需要属性的名称。
这是因为我想让更新 function 更智能,所以它只更新必须更新的内容。 它适用于 sql,它是一个存储库 function。
谢谢。
更新澄清:
我希望能够像这样调用更新:
Update(item, x => new { x.Property1, x.Property2 })
所以表达式的 IEnumerable 不是一个选项,但如果上面的内容更加困难,我会这样做......
假设您不想验证表达式是否实际返回属性值,这将起作用:
public int Update(Item item, params Expression<Func<Item, object>>[] selectors)
{
var propertyNames = selectors
.Select(expression => ((MemberExpression)expression.Body).Member.Name);
// ...
}
否则,您将需要类似于此综合答案的内容。
更新
如果你想使用匿名对象,那么你可以这样做:
public int Update<TProps>(Item item, Expression<Func<Item, TProps>> selector)
{
var propertyNames = typeof(TProps)
.GetProperties()
.Select(prop => prop.Name);
// ...
}
尽管这很容易被滥用。
如果您不介意将更新代码编写为Update(item, x => x.Property1, x=> x.Property2 )
,它会像 Johnathans 回答所示那样可读且更容易编写。
尽管如果添加泛型,则可以强制 x 为同一类型,并将其重用于Item
之外的不同对象
int Update<T>(T item, params Expression<Func<T, object>>[] selectors)
{
string getName(Expression e)
{
if(e is LambdaExpression l)
return getName(l.Body);
if(e is MemberExpression m)
return m.Member.Name;
if(e is UnaryExpression u)
return getName( u.Operand);
throw new NotImplementedException();
}
var names = selectors.Select(getName);
//update code...
}
注意,助手 function 是一个基本的助手,您可以使用更扩展的可重用助手 function 来获得名称,周围有很多
示例代码(第一个匿名 object 只是为了创建一个示例对象): Update(new { foo = "a", bar = 5}, x=>x.foo, x=>x.bar);
现在有趣的是,您可以通过删除新表达式来强制使用单个表达式,或者您可以组合 function,并且仍然允许匿名,方法是在帮助程序 function 中添加对NewExpression
的检查(更改它以允许多个名称课程):
int Update<T>(T item, params Expression<Func<T, object>>[] selectors)
{
IEnumerable<string> getName(Expression e)
{
if (e is LambdaExpression l)
return getName(l.Body);
if (e is MemberExpression m)
return new[] { m.Member.Name };
if (e is UnaryExpression u)
return getName(u.Operand);
if (e is NewExpression n) // <- to account for the anonymous object
return n.Arguments.SelectMany(getName);
throw new NotImplementedException();
}
var names = selectors.SelectMany(getName);
// etc
}
这样,您可以选择(甚至混合)。 这两个调用都产生相同的结果:
Update(new { foo = "a", bar = 5}, x=>x.foo, x=>x.bar);
Update(new { foo = "a", bar = 5 }, x => new { x.foo, x.bar});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.