用于获取属性名称的 Linq 表达式和扩展方法
我正在看这篇文章,它描述了一种在 POCO 属性之间进行数据绑定的简单方法:数据绑定 POCO 属性
Bevan 的评论之一包括一个简单的 Binder 类,可用于完成此类数据绑定。 想实施 Bevan 为改进课程而提出的一些建议,即:
- 它非常适合我的需要,但我 已分配
- 检查属性 由 sourcePropertyName 标识和 targetPropertyName 存在
- 检查类型兼容性 两个属性之间
此外,考虑到通过字符串指定属性很容易出错,您可以改用 Linq 表达式和扩展方法。 编写而不是编写,
Binder.Bind( source, "Name", target, "Name")
然后,您可以
source.Bind( Name => target.Name);
我很确定我可以处理前三个(尽管可以随意包含这些更改),但我不知道如何使用 Linq 表达式和扩展方法来编写代码而不使用属性名称字符串。
有什么建议吗?
这是链接中找到的原始代码:
public static class Binder
{
public static void Bind(
INotifyPropertyChanged source,
string sourcePropertyName,
INotifyPropertyChanged target,
string targetPropertyName)
{
var sourceProperty
= source.GetType().GetProperty(sourcePropertyName);
var targetProperty
= target.GetType().GetProperty(targetPropertyName);
source.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
targetProperty.SetValue(target, sourceValue, null);
}
};
target.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
sourceProperty.SetValue(source, targetValue, null);
}
};
}
}
I was looking at this post that describes a simple way to do databinding between POCO properties: Data Binding POCO Properties
One of the comments by Bevan included a simple Binder class that can be used to accomplish such data binding. It works great for what I need but I would like to implement some of the suggestions that Bevan made to improve the class, namely:
- Checking that source and target are
assigned - Checking that the properties
identified by sourcePropertyName and
targetPropertyName exist - Checking for type compatibility
between the two properties
Also, given that specifying properties by string is error prone, you could use Linq expressions and extension methods instead. Then instead of writing
Binder.Bind( source, "Name", target, "Name")
you could write
source.Bind( Name => target.Name);
I'm pretty sure I can handle the first three (though feel free to include those changes) but I have no clue how to use Linq expressions and extension methods to be able to write code without using property name strings.
Any tips?
Here is the original code as found in the link:
public static class Binder
{
public static void Bind(
INotifyPropertyChanged source,
string sourcePropertyName,
INotifyPropertyChanged target,
string targetPropertyName)
{
var sourceProperty
= source.GetType().GetProperty(sourcePropertyName);
var targetProperty
= target.GetType().GetProperty(targetPropertyName);
source.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
targetProperty.SetValue(target, sourceValue, null);
}
};
target.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
sourceProperty.SetValue(source, targetValue, null);
}
};
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
以下代码将从 lambda 表达式返回一个字符串形式的属性名称:
用法:
UPDATE
用法:
The following will return a property name as a string from a lambda expression:
Usage:
UPDATE
Usage:
这个问题非常类似于:Retriving Property name from lambda expression
(来自https://stackoverflow.com/a/17220748/1037948的交叉发布答案)
我不知道不知道是否需要绑定到“子属性”,但是检查
lambda.Body
中的Member.Name
只会返回“最终”属性,而不是“完全” -合格的”财产。例如)
o =>; o.Thing1.Thing2
将生成Thing2
,而不是Thing1.Thing2
。当尝试使用此方法通过表达式重载简化 EntityFramework
DbSet.Include(string)
时,这是有问题的。因此,您可以“作弊”并解析
Expression.ToString
。在我的测试中,性能似乎相当,所以如果这是一个坏主意,请纠正我。扩展方法
(检查分隔符甚至可能有点过分)
This question is very similar to: Retrieving Property name from lambda expression
(Cross-posting answer from https://stackoverflow.com/a/17220748/1037948)
I don't know if you need to bind to "subproperties", but inspecting the
lambda.Body
forMember.Name
will only return the "final" property, not a "fully-qualified" property.ex)
o => o.Thing1.Thing2
would result inThing2
, notThing1.Thing2
.This is problematic when trying to use this method to simplify EntityFramework
DbSet.Include(string)
with expression overloads.So you can "cheat" and parse the
Expression.ToString
instead. Performance seemed comparable in my tests, so please correct me if this is a bad idea.The Extension Method
(Checking for the delimiter might even be overkill)
这可能超出或不完全符合您的要求,但我已经做了类似处理两个对象之间属性映射的操作:
这允许您创建此对象的实例,然后使用“SyncToModel”和“SyncToView”来来回移动值。与此相关的以下部分允许您将多个这些东西分组并通过一次调用来回移动数据:
用法看起来像这样:
希望这有帮助!
This is likely more than or not exactly what you asked for but I've done something similar to handle mapping of a property between two objects:
This allows you to create an instance of this object and then use "SyncToModel" and "SyncToView" to move values back and forth. The following piece that goes with this allows you to group multiple of these things and move data back and forth with one call:
Usage would look something like this:
Hope this helps!
var pr = typeof(CCategory).GetProperties().Select(i => i.Name).ToList(); ;
var pr = typeof(CCategory).GetProperties().Select(i => i.Name).ToList(); ;
声明:
用法:
declaration:
Usage: