首先,这确实是一件奇怪的事情。您应该首先考虑替代设计。现在有一对夫妇来找我。
无论如何,您可以使用反射来实现您想要实现的目标。,好吧,差不多了..
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
输入参数Map
函数(将维度枚举映射到属性TVRawDataRecord
class) 被传递,因为您需要知道属性的返回类型。
我想说更好的替代设计只是制作一个简单的函数,使用 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
。第二个示例无法编译,因为返回类型与返回的类型不匹配。如果所有属性都属于同一类型,则您可以选择该类型。如果它确实如此可变,那么您将必须首先将属性转换为对象,然后再转换为T
,但仍然比反射好!
更好的方法是指定属性财产 https://stackoverflow.com/a/2820676/661933 or to enum https://stackoverflow.com/a/11008926/661933.
最重要的是如果BrandVariant
and Creative
等都是它们自己的类,您可以让它们全部实现一个接口,该接口将具有只读属性Dimension
在它们上,您可以访问电视记录属性的该属性以获得正确的尺寸值!