2017-06-20 26 views
1

我需要創建一個操作,會非常有效地反反覆覆:表達式樹演員到ICollection的<T>和添加

  1. 演員的對象類型變量的ICollection的類型變量
  2. 鑄造的對象類型變量爲T型變量
  3. 將T型項目添加到ICollection類型集合。

我的理解是,構建表達式樹並存儲重用操作是實現此目的最快的方法。我遇到了很多麻煩。爲了使這一點更加明確,我需要一個表達式樹編譯的動作,將做到這一點:

private void AddToCollection(Type itemType, object item, object collection) 
{ 
    // assume itemType is used in the expression-tree to cast to ICollection<T> 
    ((ICollection<T>)collection).Add((T)item); 
} 
+0

爲什麼不直接使用一個通用的功能?使用表達式給你什麼? – Amy

+0

對於'Type itemType'參數是不可能的。唯一可能的是爲特定的'Type'創建'Action ',然後多次調用它傳遞'object item,object collection'。對你起作用嗎? –

+0

@Amy我不能使用泛型方法,因爲我沒有類型參數。我已經使用標記了屬性的屬性反射派生了集合的實例。 – Wilshire

回答

3

這是不可能創造有效非反射代碼確實

private void AddToCollection(Type itemType, object item, object collection) 
{ 
    // Assume that itemType became T somehow 
    ((ICollection<T>)collection).Add((T)item); 
} 

因爲爲了避免反射,必須預先知道Type(具體或泛型類型的參數)。

什麼是可能的,雖然是創造這樣的:

static Action<object, object> CreateAddToCollectionAction(Type itemType) 
{ 
    // Assume that itemType became T somehow 
    return (item, collection) => ((ICollection<T>)collection).Add((T)item); 
} 

方法如下:

static Action<object, object> CreateAddToCollectionAction(Type itemType) 
{ 
    var item = Expression.Parameter(typeof(object), "item"); 
    var collection = Expression.Parameter(typeof(object), "collection"); 
    var body = Expression.Call(
     Expression.Convert(collection, typeof(ICollection<>).MakeGenericType(itemType)), 
     "Add", 
     Type.EmptyTypes, 
     Expression.Convert(item, itemType) 
    ); 
    var lambda = Expression.Lambda<Action<object, object>>(body, item, collection); 
    return lambda.Compile(); 
} 

使用範例:

var add = CreateAddToCollectionAction(typeof(int)); 
object items = new List<int>(); 
add(1, items); 
add(2, items);