Tout d'abord, c'est vraiment une chose bizarre à faire. Vous devriez d'abord penser à un design alternatif. Il y en a quelques uns qui me viennent à l'esprit maintenant.
Quoi qu'il en soit, vous pourriez utiliser la réflexion pour atteindre ce que vous essayez d'atteindre., enfin presque..
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(TVRawDataRecord obj, Dimension dimension, T valueToMatch)
{
return valueToMatch == dimension.MapToTvRecordProperty(obj);
}
T MapToTvRecordProperty(this Dimension dimension, TVRawDataRecord obj)
{
return obj.GetPropertyValue(dimension.ToString());
}
T GetPropertyValue(this TVRawDataRecord obj, string propertyName)
{
var property = typeof(TVRawDataRecord).GetProperty(propertyName);
if (property == null)
return null; //ou lancer ce que vous voulez
return (T)property.GetValue(obj, null);
}
Strictement non testé, non compilé. Mais cela devrait donner une idée de comment cela se fait. Vous pouvez rendre la fonction GetPropertyValue
plus générique, mais c'est une autre chose. L'argument de type T
dans la fonction Map
(qui mappe un enum dimension à une propriété de la classe TVRawDataRecord
) est passé car vous devez connaître le type de retour de la propriété.
Je dirais qu'une meilleure conception alternative est simplement de créer une fonction simple qui utilise une logique if else pour retourner le bon type. Donc changez la fonction Map
à ceci:
T MapToTvRecordProperty(this Dimension dimension, TVRawDataRecord obj)
{
switch (dimension)
{
case Dimension.BrandVariant:
return obj.BrandVariant;
case Dimension.Creative:
return obj.Creative;
.....
default:
throw;
}
}
L'avantage est que même si, à l'avenir, vous changez le nom de l'une des variables, votre code ne se cassera pas (contrairement à l'approche de réflexion). Mais le problème ici est de choisir le type de retour T
. Le deuxième exemple ne compilerait pas car le type de retour ne correspond pas à ce qui est retourné. Si toutes les propriétés sont du même type, vous pouvez choisir ce type. Si c'est vraiment variable, alors vous devrez d'abord caster votre propriété en objet puis en T
, mais toujours mieux que la réflexion !!
Une approche encore meilleure serait de spécifier des attributs soit à la propriété ou à l'enum.
Et surtout si BrandVariant
et Creative
etc sont des classes à part entière, vous pouvez les faire toutes implémenter une interface qui aura une propriété en lecture seule Dimension
sur eux et vous pourrez accéder à cette propriété de vos propriétés d'enregistrement tv pour obtenir la bonne valeur de dimension!