簡體   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