通过表达式获取/设置属性

本文关键字:设置 属性 获取 表达式 | 更新日期: 2023-09-27 18:10:59

尝试通过将字段从 oracle 数据库映射到对象的属性来创建数据访问组件。我创建了一个采用类型并像这样调用的基本对象...

public class Document : DataProviderBase<DataObjects.Document> 
{ 
    // code goes here... 
}

此基对象具有一个名为 AddMapping 的方法,该方法将数据库字段映射到如下所示的属性...

this.AddMapping<int>("ATD_KEY", "Key")

在这种情况下...

  • int是属性的类型
  • 数据库中的字段名称ATD_KEY
  • KeyDataObjects.Document上的属性名称

代码使用...

typeof(<TParent>).GetProperty(<property name>)

..获取用于获取和设置属性的PropertyInfo。虽然这很棒,但我想在 AddMapping 方法中添加一些类型安全和 lambda 表达式。我想做如下事情...

this.AddMapping<int>("ATD_KEY", o => o.Key)

..其中o属于 DataProviderBase 提供的类型。这将确保属性Key实际上是int类型,并确保字符串"Key"不会拼写错误或大小写错误,就像第一个AddMapping方法中显示的当前工作代码存在问题一样。

这可能吗?如果是,如何?

我发现的最接近的例子是这个来自类对象的属性的动态表达式,但这仍然按字符串而不是表达式引用属性。

通过表达式获取/设置属性

你可以使用如下的东西:

public void AddMapping<T>(fieldName, Expression<Func<TParent, T>> propExpr)
{
    var memberExpr = (MemberExpression)propExpr.Body;
    PropertyInfo property = (PropertyInfo)memberExpr.Member;
    ...
}

当然有可能:

public static PropertyInfo GetProperty<TParent>(Expression<Func<TParent, object>> prop)
{
    var expr = prop.Body;
    if (expr.NodeType == ExpressionType.Convert)
        expr = ((UnaryExpression)expr).Operand;
    if (expr.NodeType == ExpressionType.MemberAccess)
        return ((MemberExpression)expr).Member as PropertyInfo;
    throw new ArgumentException("Invalid lambda", "prop");
}
public void AddMapping<TParent>(fieldName, Expression<Func<TParent, object>> prop)
{
    AddMapping(fieldName, GetProperty(prop).Name);
}

此方法的优点是只需要一个类型参数(TParent(。传入一个 lambda,该 lambda 可能包含对属性类型的强制转换。我们摆脱它,然后得到成员表达式。