【问题标题】:LINQ, get string list using dynamic field nameLINQ,使用动态字段名称获取字符串列表
【发布时间】:2016-09-13 07:06:47
【问题描述】:

所以我想从表中返回一个具有唯一值的字符串类型的列表。

值得注意的是,该表的设计者决定表中的每一行都包含多个具有多个唯一字段的列。因此,您不能只从需要指定字段的表中获取唯一的项目列表,然后变得不同。

为此,我想编写一个通用方法,我可以在其中指定列名并获取唯一的项目列表。

我尝试了很多方法,下面列出了两种;

retList = context.LP_Specification.Select(x => x.GetType().GetProperty(fieldName).GetValue(x).ToString()).Distinct().ToList();

retList = context.LP_Specification.Select(fieldName) 

也不行。

但是,我使用这样的反射会出错。

所以方法调用是这样的;

public List<string> GetSpecs(string fieldName)

我想从表中获取字符串值列表,并且只返回指定字段的不同值。

【问题讨论】:

  • 类似stackoverflow.com/questions/39223586/…?但是,如果您始终选择 string 列,您的情况可能会更简单,对吗?
  • Select(s => s.GetType().GetProperty(Property.Name).GetValue(s)) (今天早些时候没有 ToString() 为我工作......希望有帮助(只是我的 0.02 美元,当加到两美分时产生约 0.015 美元)...具体来说,它是 Select(s =>(double) s.GetType().GetProperty("Customers").GetValue(s)).ToArray() ;
  • "也不起作用。但是我在使用这样的反射时遇到错误。"更加详细一些!你得到什么错误?你能指望什么?我认为我们可以从 15k 用户那里获得这些基本信息,不是吗?

标签: c# linq


【解决方案1】:

您不需要使用反射获取每个对象的属性值,因为此查询将针对数据库执行,因此该方法不起作用(除非查询内存中的集合) .

您需要构建一个动态表达式树来实现您想要的。一个简单的例子是这样的:

// Building expression x=> x.FieldName
ParameterExpression foo = Expression.Parameter(typeof(Foo), "x");
MemberExpression selection = Expression.PropertyOrField(foo, "FieldName");
var lambdaExp = Expression.Lambda<Func<Foo, string>>(selection, foo);

用法:

retList = context.LP_Specification.Select(lambdaExp).Distinct();

以上假设实体类型为Foo,属性名为"FieldName"

您总是可以从中创建扩展方法:

public static class MyExtensions
{
    public static IQueryable<V> SelectByName<T, V>(this IQueryable<T> source, 
                                                        string FieldName)
    {
        ParameterExpression paramExp = Expression.Parameter(typeof(T), "x");
        MemberExpression memberExp = Expression.PropertyOrField(paramExp, FieldName);
        var lambdaExp = Expression.Lambda<Func<T, V>>(memberExp, paramExp);

        return source.Select(lambdaExp);
    }
}

用法:

retList = context.LP_Specification
                 .SelectByName<LP_Specification, string>("SomeFieldName").Distinct();

【讨论】:

  • 你需要反射来找到SomeFieldName的类型;)。
  • @shA.t 用户说她只在寻找字符串属性。
  • 我认为,OP 需要任何类型的List&lt;string&gt; 的结果;)。
  • 谢谢,效果很好。但我需要两列!我需要做什么?
【解决方案2】:

我认为你可以使用这样的通用方法:

private IEnumerable<string> GetResult<T>(IEnumerable<T> list, string propName)
{
    var retList = new List<string>();

    var prop = typeof (T).GetProperty(propName);
    if (prop == null)
        throw new Exception("Property not found");

    retList = list.Select(c => prop.GetValue(c).ToString()).ToList();
    return retList;
}

然后这样称呼它:

var result = GetResult(context.LP_Specification, "FieldName");

【讨论】:

    【解决方案3】:

    如果列数基本是静态的,你应该可以试试这个。这消除了对反射和复杂表达式树的需求;

    // this will be used in all querys; add 'where' clauses etc if you want
    IQueryable<Specification> rootQuery = from s in specification select s;
    
    IQueryable<string> names = null;
    switch(fieldName)
    {
        case "field1": names = rootQuery.Select(r => r.field1); break;
        case "field2": names = rootQuery.Select(r => r.field2); break;
        case "field3": names = rootQuery.Select(r => r.field3); break;
        default: throw new ArgumentOutOfRangeException("Unknown field: " + fieldName);
    }
    
    var strings = names.Distinct().ToList();
    

    【讨论】:

      猜你喜欢
      • 2011-12-17
      • 2021-08-15
      • 2012-01-17
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 2011-03-28
      相关资源
      最近更新 更多