将var作为T参数传递

时间:2015-06-26 07:41:51

标签: c# linq dynamic lambda

我正在尝试构建OrderBy表达式问题是当我将var对象传递给TSource时,Type for TSource将是对象而不是Actual Column类型 例如,Actual类型是int,但TSource类型是object。

Type tblType = tblObj.GetType();
PropertyInfo propinfo;
propinfo = tblType.GetProperty(ColumnName);
if (propinfo == null)
{
    return null;
}
var instance = Activator.CreateInstance(propinfo.PropertyType);
result = result.OrderBy(GetOrder(item.ColumnName, tblObj, instance));

这是lambda表达式构建器

public Expression<Func<T, TSource>> GetOrder<T,TSource>(string field, T item,TSource source)
    {
        if (string.IsNullOrEmpty(field))
        {
            return null;
        }
        var param = Expression.Parameter(typeof(T), "c");
        Expression conversion = Expression.Convert(Expression.Property
        (param, field), typeof(TSource));  
        return Expression.Lambda<Func<T, TSource>>(conversion, param);
    }

4 个答案:

答案 0 :(得分:4)

如果不确定类型,可以使用dynamic,以便在运行时级别找到类型。

result = Enumerable.OrderBy(
       result, 
       GetOrder(item.ColumnName, tblObj, (dynamic)instance));

答案 1 :(得分:2)

您必须使用dynamic关键字或使用反射。 但是,您可以更轻松地使用dynamic解决您的问题。 唯一的问题是,扩展方法不会被动态调度。 因此,您必须将扩展方法称为简单的静态方法:

result = Enumerable.OrderBy(
           result, 
           GetOrder(item.ColumnName, tblObj, instance as dynamic));

此外,您可以提出问题&#34; 为什么无法动态调度扩展方法?&#34;

asnwer by @EricLippert

  

这意味着为了获得动态扩展方法的调用   正确解决,不知何故,DLR必须在运行时知道所有内容   命名空间嵌套和&#34;使用&#34;指令在你的来源   码。我们没有一个方便编码所有这些的机制   信息进入呼叫站点。我们考虑发明这样的   机制,但决定它成本太高,产生太多   安排风险是值得的。

因此,CLR必须找到包含扩展方法的命名空间。 CLR搜索它并找到方法命名空间,然后它只是更改为result.OrderByEnumerable.OrderBy(result, ...)。但是,如果是dynamic关键字,DLR(动态语言运行时)必须在运行时找到此方法的类,同样基于包含的命名空间。微软团队正确认为成本太高,无法实施。

答案 2 :(得分:0)

方法Activator.CreateInstance(Type type)返回object,而不是int。 也许你应该在使用之前将它拆箱到int;

答案 3 :(得分:0)

遵循文档Activator.CreateInstance返回对象,因此您必须将其强制转换为目标类型,或者您可以使用dynamic类型,但编译器无法检查类型。