表达式树转换为ICollection <t>&amp;加

时间:2017-06-20 18:02:27

标签: c# expression-trees

我需要创建一个非常有效且重复的Action:

  1. 将对象类型变量强制转换为ICollection类型变量
  2. 将对象类型变量强制转换为T型变量
  3. 将T型项添加到ICollection类型集合中。
  4. 我的理解是构建表达式树并存储动作以便重用是最快的方法。我遇到了很多麻烦。为了使这一点更清楚,我需要一个表达式树编译动作来执行此操作:

    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);
    }
    

1 个答案:

答案 0 :(得分:4)

无法有效地创建 非反射代码

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);