3
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); 
 }

TVRawDataRecordsのリストを列挙型のリストと比較し、Dimensions一致しない場合にそれらを新しいDimensionIemリストに追加するLinqクエリを作成しようとしています。これはすべて正常に機能しますが、ディメンション値はプロパティ名と同じであるためp.BrandVariant、ステートメントの をディメンション列挙値に動的に置き換える必要があります。これは、これらの数行のコードだけで 8 次元などをループできることを意味します。WhereTVRawDataRecord

Whereステートメントにディメンションを含める方法を誰かが説明できますか? ありがとう!

4

1 に答える 1

1

何よりもまず、これは本当に奇妙なことです。最初に別のデザインを考えるべきです。今、私のところに来ているカップルがいます。

とにかく、リフレクションを使用して、達成しようとしていることを達成できます。、 よくほとんど..

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型引数が渡されます。MapTVRawDataRecord

より良い代替設計は、 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。戻り値の型が返されるものと一致しないため、2 番目の例はコンパイルされません。すべてのプロパティが同じタイプの場合は、そのタイプを選択できます。それが非常に可変である場合は、最初にプロパティをオブジェクトにキャストし、次に にキャストする必要がありますTが、それでもリフレクションよりは優れています!!

さらに良いアプローチは、属性を propertyまたはenumに指定することです。

BrandVariantおよびCreativeetc が独自のクラスである場合は、読み取り専用のプロパティを持つインターフェイスをすべて実装することDimensionができ、テレビ レコード プロパティのそのプロパティにアクセスして、適切なディメンション値を取得できます。

于 2012-11-22T23:55:09.457 に答える