繁体   English   中英

在Linq查询中使用动态列名称

[英]Using Dynamic Column Names in a Linq Query

foreach (Dimension dimensions in Enum.GetValues(typeof(Dimension)))
{
    var r = new ReferenceTable(dimensions).referenceItems;
    List<TVRawDataRecord> qry = TVRawDataList.Where(p => !r.Any(d => d.Value == p.BrandVariant))
                                             .ToList();                
    DimensionItem di = new DimensionItem(qry, dimensions);
    newDimensions.Add(di); 
 }

我想创建一个LINQ查询比较列表TVRawDataRecords中的枚举的Dimensions和那里是没有匹配然后将它们添加到一个新的DimensionIem列表。 这一切都运行正常但我需要动态p.BrandVariant我的Where语句中的p.BrandVariant和维度枚举值,因为维度值与TVRawDataRecord属性名称相同。 这意味着我可以只用这几行代码来循环遍历8个维度等。

有人可以解释我如何在Where语句中包含维度吗? 谢谢!

首先,这真的是一件奇怪的事情。 您应该首先考虑替代设计。 现在有一对夫妇来找我。

无论如何,你可以使用反射来实现你想要实现的目标。 ,差不多......

foreach (Dimension dimension in Enum.GetValues(typeof(Dimension)))
{
    var r = new ReferenceTable(dimension).referenceItems;
    var qry = TVRawDataList.Where(p => !r.Any(d => IsAMatch(p, dimension, d.Value)))
                           .ToList();     

    DimensionItem di = new DimensionItem(qry, dimension);
    newDimensions.Add(di); 
}

bool IsAMatch<T>(TVRawDataRecord obj, Dimension dimension, T valueToMatch)
{
    return valueToMatch == dimension.MapToTvRecordProperty<T>(obj);
}

T MapToTvRecordProperty<T>(this Dimension dimension, TVRawDataRecord obj)
{
    return obj.GetPropertyValue<T>(dimension.ToString());
}

T GetPropertyValue<T>(this TVRawDataRecord obj, string propertyName)
{
     var property = typeof(TVRawDataRecord).GetProperty(propertyName);
     if (property == null)
         return null; //or throw whatever

     return (T)property.GetValue(obj, null);
}

严格未经测试,未编译。 但这应该让人知道它是如何完成的。 您可以使GetPropertyValue函数更通用,但这是另一回事。 传递Map函数中的T类型参数(将维度枚举映射到TVRawDataRecord类的属性),因为您需要知道属性的返回类型。

我想说一个更好的替代设计只是创建一个简单的函数,使用if else逻辑来返回正确的类型 所以将Map功能更改为:

T MapToTvRecordProperty<T>(this Dimension dimension, TVRawDataRecord obj)
{
    switch (dimension)
    {
        case Dimension.BrandVariant:
            return obj.BrandVariant;
        case Dimension.Creative:
            return obj.Creative;

        .....

        default:
            throw;
    }
}

优点是,即使将来更改任何变量的名称,您的代码也不会中断(与反射方法不同)。 但这里的问题是选择返回类型T 第二个例子不会编译,因为返回类型与返回的内容不匹配。 如果所有属性属于同一类型,则可以选择该类型。 如果它真的是变量,那么你必须首先将你的属性转换为object然后转换为T ,但仍然比反射更好!

更好的方法是指定属性或枚举 属性

最重要的是,如果BrandVariantCreative等都是他们自己的类,你可以让他们都实现一个接口,在它们上面只有一个属性readonly Dimension ,你可以访问你的tv记录属性的属性,以获得正确的维度值!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM