式を分析して PropertyInfo を取得する利点は、コンパイル時のチェックが可能になり、リファクタリングのサポートが向上することです。
たとえば、プロパティの名前を Bar から Barr に変更すると、コードがコンパイルされなくなるため、アプリケーションを実際に実行しなくても、無効なメンバー アクセスのバグを見つけることができます。
どのプロパティにアクセスする必要があるかが事前にわかっている場合は、式を使用することをお勧めします。
たとえば、グリッド列やリスト コントロールにバインドするプロパティの名前を指定する必要があるデータ バインド シナリオでは、式が特に役立つことがわかりました。このタイプのシナリオで式を使用すると、メンテナンス コストが大幅に削減されます。
式を使用して、独自の PropertyHelper クラスでグリッド列の書式設定を実行する例を次に示します。
GridForm.FormatGrid() にジャンプして、重要なビットを表示します。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq.Expressions;
using System.Reflection;
using System.Windows.Forms;
namespace ExpressionSample
{
public class TestEntity
{
public int ID { get; set; }
public string Text { get; set; }
public decimal Money { get; set; }
}
public partial class GridForm : Form
{
public GridForm()
{
this.InitializeComponent();
}
private void GridForm_Load(object sender, EventArgs e)
{
this.FillGrid();
this.FormatGrid();
}
private void FillGrid()
{
this.DataGridView.DataSource = TestDataProducer.GetTestData();
}
private void FormatGrid()
{
var redCellStyle = new DataGridViewCellStyle() { ForeColor = Color.Red };
var moneyCellStyle = new DataGridViewCellStyle() { Format = "$###,###,##0.00" };
this.GridColumn(e => e.ID).Visible = false;
this.GridColumn(e => e.Text).DefaultCellStyle = redCellStyle;
this.GridColumn(e => e.Money).DefaultCellStyle = moneyCellStyle;
}
private DataGridViewColumn GridColumn<TProperty>(Expression<Func<TestEntity, TProperty>> expr)
{
var propInfo = PropertyHelper<TestEntity>.GetProperty(expr);
var column = this.DataGridView.Columns[propInfo.Name];
return column;
}
}
public static class PropertyHelper<T>
{
public static PropertyInfo GetProperty<TValue>(
Expression<Func<T, TValue>> selector)
{
Expression body = selector;
if (body is LambdaExpression)
{
body = ((LambdaExpression)body).Body;
}
switch (body.NodeType)
{
case ExpressionType.MemberAccess:
return (PropertyInfo)((MemberExpression)body).Member;
default:
throw new InvalidOperationException();
}
}
}
public static class TestDataProducer
{
public static IList<TestEntity> GetTestData()
{
var entities = new List<TestEntity>();
for (var i = 1; i <= 10; i++)
{
var testEntity = new TestEntity {
ID = i,
Text = "Entity " + i.ToString(),
Money = i * 100m
};
entities.Add(testEntity);
}
return entities;
}
}
}