【问题标题】:Passing var as T parameter将 var 作为 T 参数传递
【发布时间】:2015-06-26 07:41:50
【问题描述】:

我正在尝试构建 OrderBy 表达式,问题是当我将 var 对象传递给 TSource 时,TSource 的类型将是对象而不是实际列类型 例如 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);
    }

【问题讨论】:

  • 请注意,没有 var 对象或 var 类型。 var 只是意味着编译器推断类型,因此您在声明变量时不必显式写下它。 Activator.CreateInstance 返回object,所以你的行相当于object instance = Activator.CreateInstance(propinfo.PropertyType);

标签: c# linq dynamic lambda


【解决方案1】:

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

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

【讨论】:

  • 最后,dynamic 的合法用途感觉像黑客!
【解决方案2】:

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

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

另外,你可以问一个问题“为什么扩展方法不能动态调度?”

asnwer by @EricLippert

也就是说为了得到一个动态的扩展方法调用 正确解决,不知何故 DLR 必须在运行时知道所有 命名空间嵌套和“使用”指令在您的源代码中 代码。我们没有一种方便的机制来编码所有这些 信息进入呼叫站点。我们考虑发明这样一个 机制,但认为成本太高,产量太大 安排风险是值得的。

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

【讨论】:

    【解决方案3】:

    方法 Activator.CreateInstance(Type type) 返回对象,而不是 int。 可能您应该在使用前将其拆箱为 int;

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-30
        • 1970-01-01
        • 2015-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        相关资源
        最近更新 更多