最近開始重複利用先前寫的底層,於是又思考了Property的Getter與Setter是否可以有更好的設計?
先前的設計是使用static field來記錄Property的基本資訊,為了避免日後造成麻煩,因此使用Expression做為Constructor參數,再透過Expression拆解,取出Property Name,建立Dictionary來存放Property value。
使得Property的宣告看起來大概就像
static Property<T, bool> _IsValid = RegisterProperty<bool>(entity => entity.IsValid, "是否合法");
public bool IsValid
{
get { return this.GetProperty(_IsValid); }
private set { this.SetProperty(_IsValid, value); }
}
我第一個想法是想要把GetProperty<P>(Property<T, P>)改為GetProperty<P>(Expression<Func<T, P>> property),直接拿Expression當Dictionary Key,但是結果發現每次都會產生新的Expression Instance,還真是不意外....
那麼如果將GetProperty & SetProperty改為每次拆解Expression呢?
實驗開始,先大概寫出底層的樣子
public class Entity<T> where T :Entity<T>
{
private ConcurrentDictionary<string, object> _Properties;
public string Name
{
get;
set;
}
public string NameByDictionary
{
get { return (string)this._Properties["Name"]; }
set { this._Properties.AddOrUpdate("Name", value, (key, v) => v); }
}
public string NameByExpressionName
{
get { return (string)this.GetPropertyByName(entity => entity.Name); }
set { this.SetPropertyByName(entity => entity.Name, value); }
}
public Entity()
{
this._Properties = new ConcurrentDictionary<string, object>();
}
public P GetPropertyByName<P>(Expression<Func<T, P>> property)
{
var member = GetMember(property);
return (P)this._Properties[member.Name];
}
public void SetPropertyByName<P>(Expression<Func<T, P>> property, P newValue)
{
var member = GetMember(property);
this._Properties[member.Name] = newValue;
}
public static MemberInfo GetMember<P>(Expression<Func<T, P>> member)
{
if (member.Body.NodeType == ExpressionType.MemberAccess)
{
return ((MemberExpression)member.Body).Member;
}
throw new ArgumentException("Not a member access", "member");
}
}