[英]What is the advantage of setting `BaseAddress` property of `HttpClient`
[英]what's the advantage of Property Info?
在.net FrameWork 3.5中,我們可以使用下面提到的代碼獲取屬性信息。
using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo
{
public string Bar { get; set; }
}
static class Program
{
static void Main()
{
PropertyInfo prop = PropertyHelper<Foo>.GetProperty(x => x.Bar);
}
}
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();
}
}
}
這也可以通過創建類的實例並訪問屬性成員來完成。 那么,物業信息的優勢是什么?
PropertyInfo
用於獲取類的屬性信息。 不需要創建實例。 優點是消除了鍵入錯誤的可能性。
Expressions
是完全不同的概念(內部使用Reflection)。 表達式用於將方法主體表示為樹結構。 這允許在運行時靈活地創建/調整方法定義。
Queryable類利用Expressions的這種功能在遠程源上構建/執行動態查詢。
例如,考慮INotifyPropertyChanged
接口。 用於屬性更改通知。
通常的實現將屬性名稱作為字符串參數。 因此在運行時檢測到鍵入錯誤。 重構也會破壞代碼(盡管智能重構工具會解決此問題)。
void RaisePropertyChanged(PropertyChangedEventArgs args)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
public string Name
{
set
{
_name = value;
RaisePropertyChanged("Name"); // Property name is specified as string
}
}
更好的實現(雖然性能不高)將屬性名稱作為Expression
。
void RaisePropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
var handler = PropertyChanged;
if (handler != null)
{
MemberExpression body = selectorExpression.Body as MemberExpression;
handler(this, new PropertyChangedEventArgs(body.Member.Name));
}
}
public string Name
{
set
{
_name = value;
RaisePropertyChanged( () => this.Name); // Property is specified instead of name that removes typing error
}
}
通過剖析表達式獲得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;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.