使用lambda表达式读取属性值

时间:2009-07-07 18:30:09

标签: c# reflection lambda

我正在为我的应用程序编写一个文件通用块,并开始使用Lambda表达式管理我的规则集以生成块,以避免魔术字符串,配置地狱等的陷阱。

在我的映射类中,我的行类似于:

Map(x => x.Name).Length(20).PadLeft(true).PaddingChar("#");

这个工作正常,不是我的问题所在的地方,我设置保存表达式的信息是在Map方法中:

public override IPropertyMap Map(Expression<Func<T, object>> expression)
{
    var propertyMap = new FixedLengthPropertyMap
          {
              //Length = 20,
              //PaddingCharacter = " ",
              PadLeft = false,
              PropertyInfo = ReflectionHelper.GetProperty(expression)
          };

    _properties.Add(propertyMap);

    return propertyMap;
}

_properties只是一个List<IPropertyMap>,它存储了我的信息,我的问题是从目前我想出的类似于此的属性中读取真实对象数据的最佳方式:

var map = new AgentMap();
var agent = new Agent {Name = "Bob"};

string output = map.Write(agent);

public override string Write<T>(T agent)
{
    var initial = _properties[0];
    return initial.PropertyInfo.GetValue(agent, null) as string;
}

有没有比使用GetValue方法更好的方法,因为之前我正在使用表达式树?

2 个答案:

答案 0 :(得分:1)

我不明白为什么你真的需要使用表达式树。只需将Map方法设为Func<T, object>并存储:

即可
public override IPropertyMap Map(Func<T, string> fetcher)
{
    var propertyMap = new FixedLengthPropertyMap
          {
              //Length = 20,
              //PaddingCharacter = " ",
              PadLeft = false,
              Delegate = fetcher // Delegate is of type Delegate
          };

    _properties.Add(propertyMap);

    return propertyMap;
}

然后:

public override string Write<T>(T agent)
{
    var initial = _properties[0];
    Func<T, string> fetcher = (Func<T, string>) initial.Delegate;
    return fetcher(agent);
}

您是否有任何理由想要了解该属性并使用表达式树?

答案 1 :(得分:1)

在某种程度上,这取决于您的方案是什么。 “简单”的答案是只编译表达式并调用它,但是如果你在紧密的循环中执行它会产生潜在的性能影响(传递委托会快得多)。

我不确定是否会在这个特定的情况下应用(因为agent),但为了避免做太多的表达式编译,你可以寻找简单的场景和直接从表达式树中读取值;一点PropertyInfo / FieldInfo比编译它更快......

有关更多信息,请查看TryEvaluate here,以及Compile如何将其用作备份策略(尽管您具有已知委托类型的优势)。