在Linq查询中使用动态列名 [英] Using Dynamic Column Names in a Linq Query

查看:118
本文介绍了在Linq查询中使用动态列名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 到枚举维度中的那些,那里没有匹配,然后将它们添加到新的 DimensionIem 列表。这一切都可以正常工作,但是我需要在我的 Where 语句中将维度枚举值替换为$ code> p.BrandVariant 维度值与 TVRawDataRecord 属性名称相同。这将意味着我可以只有这几行代码循环通过8维等。

I am trying to create a Linq query that compares a list of TVRawDataRecords to those in an enum of Dimensions and where there is no match then add them to a new DimensionIem list. This all works fine but I need to substitute dynamically the p.BrandVariant in my Where statement with the dimensions enum value as the dimension value is the same as the TVRawDataRecord property name. This would mean I can have just these few lines of code to loop through 8 dimensions etc.

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

Can someone explain how I include the dimension in my Where statement? Thanks!

推荐答案

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

First and foremost this is really a bizarre thing to do. You should think of an alternate design first. There are a couple coming to me now.

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

Anyway you could use reflection to achieve what you are trying to achieve., well almost..

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 函数更通用,但这是另一回事。 T c> c 中的参数函数(将维度枚举映射到 TVRawDataRecord class),因为你需要知道属性的返回类型。

Strictly untested, uncompiled. But this should give an idea how it is done. You can make the GetPropertyValue function more generic, but that's a different thing. The T type argument in Map function (that maps a dimension enum to property of TVRawDataRecord class) is passed since you need to know the return type of the property.

我会说一个更好的替代设计只是使一个简单的功能,如果else逻辑返回正确的类型。因此,将映射函数更改为:

I would say a better alternate design is just to make a simple function that uses if else logic to return the right type. So change Map function to this:

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 。第二个例子将不会编译,因为返回类型不匹配返回的内容。如果所有属性的类型相同,则可以选择该类型。如果它真的很可变,那么你必须首先投放你的财产来反对,然后再转到 T ,但仍然比反思更好!

The advantage is that even if in future you change the name of any of the variables, your code wouldn't break (unlike the reflection approach). But the catch here is to choose the return type T. The second example wouldnt compile since return type doesnt match what is being returned. If all the properties are of the same type, then you can choose that type. If it's so really variable, then you will have to cast your property first to object and then to T, but still better than reflection!!

更好的方法是将属性枚举

An even better approach would be to specify attributes either to property or to enum.

最重要的是,如果 BrandVariant Creative etc是自己的类,你可以使它们都实现一个接口,它将只有一个属性只读 Dimension ,你可以访问该属性您的电视记录属性获取正确的维度值!

And best of all if BrandVariant and Creative etc are classes of their own, you can make them all implement an interface which will have a property readonly Dimension on them and you can access that property of your tv record properties to get the right dimension value!

这篇关于在Linq查询中使用动态列名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆