【问题标题】:Check property type at runtime and give the same type to Generic lambda expression parameter T在运行时检查属性类型并将相同的类型赋予通用 lambda 表达式参数 T
【发布时间】:2012-11-06 10:36:58
【问题描述】:

我有一些代码 sn-p 如下所示:

想通过在运行时检查类型来解决这种情况。

PropertyInfo pi = type.GetProperty("propertyName");

var expression = new Object(); // this give me error after expression runs!

    // Want to resolve this conditation by checking the type at runtime.
    if (pi.PropertyType == typeof(DateTime))
            {
               // Want to pass the generic type parameter which has a same type created at runtime by identifying the property type.
                expression = BuildExpression<T, DateTime>(data, group.Member);
            }

private Func<T, V> BuildExpression<T, V>(IEnumerable<T> items, string propertyName)
    {
      Type type = typeof(T);
      PropertyInfo pi = type.GetProperty(propertyName);
      Type PropertyType = pi.DeclaringType;
      var parameter = Expression.Parameter(typeof(T), propertyName);
      var cast = Expression.TypeAs(parameter, pi.DeclaringType);
      var getterBody = Expression.Property(cast, pi);
      var exp = Expression.Lambda<Func<T, V>>(getterBody, parameter);
      return exp.Compile();
    }

问题: 我必须在类型上写条件我必须通过反射检查属性的类型,然后必须构建表达式。

我想要什么: 我想检查属性类型的运行时时间,并想构建与属性类型相同的该类型的运行时通用参数。

基本上我想删除If 条件关于类型检查 而我想要的是,代码应该automatically detect the property type 并在Generic parameter argument 中传递相同的类型,这样我就不会'不必检查所有具有If 条件的类型。喜欢string, decimal, double etc..

能否请您告诉我该解决方案,因为我想在运行时检查 property 类型并希望创建具有 与属性相同类型的 Generic parameter type

【问题讨论】:

  • 那么,您的BuildExpression 方法是什么?它可以采用Type 参数而不是T 泛型吗?
  • Marc,它采用泛型参数类型。我在问题中添加了相同的方法。
  • 你的expression局部变量的类型是什么?
  • 我想知道,因为我不确定如何初始化我的局部变量,因为在运行时不同的类型检查会有所不同。我已经将上面的代码发布在我认为应该的位置喜欢它。但不知道如何处理这种类型的条件......我已经用“var expression = new Object();”进行了初始化,但在表达式运行后它给了我错误!

标签: c# .net linq generics lambda


【解决方案1】:

拥有一个返回 Func&lt;T,V&gt; 的方法(对于对象 T 和成员类型 V)是有问题的,因为在运行时你不能真正用它做任何有用的事情。在编译时不知道TV 的情况下,您不能将其分配给类型化委托,并且使用DynamicInvoke 不是一个好主意。坦率地说,您最好构建一个Func&lt;object,object&gt;,并在运行时处理object。反射和泛型不能很好地混合。

private static Func<object, object> BuildExpression(
    Type type, string propertyName)
{
    var parameter = Expression.Parameter(typeof(object));
    var body = Expression.TypeAs(Expression.PropertyOrField(Expression.TypeAs(
        parameter, type), propertyName), typeof(object));
    return Expression.Lambda<Func<object, object>>(body, parameter).Compile();
}

但是,IMO 到那时,您可以切换到像 FastMember 这样的库,并使用基于名称的访问:

var accessor = TypeAccessor.Create(type);
var obj = ...
var propVal = accessor[obj, propertyName];

【讨论】:

  • 马克,谢谢你的信息。使用您的方法后,我得到了 的 LamdaExpression。没关系。让我们假设,我想以此构建“整数”类型的 lamda 表达式。我如何将结果从您的方法转换为“整数”表达式??
  • @nunu 将其作为“整数表达式”会导致巨大的问题,因为您不能拥有“整数表达式或字符串表达式或日期时间表达式或......”的变量 -但是,您可以拥有“对象表达式”。你到底想做什么?如果它是一个整数表达式,你会如何看待自己使用它?
  • 我想在这里做的是,无论我从你的方法 'BuildExpression 得到什么结果(Func),我都想使用这个结果 Func。例如。 var expResult = BuildExpression(typeof(T), "City"); var gropupedResult = myList.GroupBy(expResult);我将如何实现这一目标?
  • @nunu 我不会开始的;不过,我可能会写一个自定义的GroupBy&lt;T&gt;(this IEnumerable&lt;T&gt;, string memberName),基本上是从这个自定义的OrderBy 中借用代码答案:stackoverflow.com/questions/41244/dynamic-linq-orderby/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多