2013-09-30 15 views
2

而不是使用反射,我怎樣才能使用表達式樹來設置和獲取對象屬性?如何以最佳方式使用表達式樹來獲取和設置屬性?

我寫了下面的類,它工作得很好:

public class PropertyAccessor<TEntity> 
    { 
     private readonly PropertyInfo _memberInfo; 
     private readonly TEntity _nom; 

     public PropertyAccessor(Expression<Func<TEntity, object>> fieldSelector, TEntity nom) 
     { 
      if (fieldSelector.Body is MemberExpression) 
       _memberInfo = (PropertyInfo)((MemberExpression)fieldSelector.Body).Member; 

      else if (fieldSelector.Body is UnaryExpression) 
       _memberInfo = (PropertyInfo)((MemberExpression)((UnaryExpression)fieldSelector.Body).Operand).Member; 
      else 
       throw new NotImplementedException("Field selector not supported"); 

      _nom = nom; 
     } 

     public object Value 
     { 
      get { return _memberInfo.GetValue(_nom, null); } 
      set { _memberInfo.SetValue(_nom, value, null); } 
     } 
    } 

,我使用它是這樣的:

Product product = ProductFactory.Build(); 
var propertyAccessor = new PropertyAccessor<Product>(p => p.Name, product); 
var name = propertyAccessor.Value; 

有沒有什麼辦法,以進一步提高其性能?實施是否是最好的方法?

不應該在構造函數調用之前或之後調用表達式上的Compile()方法嗎?

將lambda表達式傳遞給該lambda表達式的表達式時會發生什麼?

是否將MemberExpression轉換爲PropertyInfo最佳選項?任何性能處罰?

+0

你不使用反射? 'PropertyInfo'屬於反射! –

+0

我也這麼認爲,這就是爲什麼我問這個問題,用Expression實現這個類的最好方法是什麼。 –

+0

您可能正在尋找[this](http://stackoverflow.com/a/3475985/2530848) –

回答

0

請記住,屬性實際上是兩個單獨的方法,get和set。我也沒有看到在這裏使用表達式的任何理由,所以我使用了代表。如果你必須使用表達式,你可以先編譯它。

public class PropertyAccessor<TEntity,TProperty> 
{ 
    private readonly TEntity _nom; 
    Func<TEntity, TProperty> _getter; 
    Action<TEntity, TProperty> _setter; 

    public PropertyAccessor(Func<TEntity, TProperty> getter, Action<TEntity, TProperty> setter, TEntity nom) 
    { 
     _getter = getter; 
     _setter = setter; 
     _nom = nom; 
    } 

    public object Value // the return type can be changed to TProperty 
    { 
     get { return _getter(_nom); } 
     set { _setter(_nom, (TProperty)value); } 
    } 
} 

這可以這樣調用:

var propertyAccessor = new PropertyAccessor<Product, String>(p => p.Name, (p, v) => p.Name = v, product);