Mappage automatique des colonnes à l'aide de la réflexion et de l'expression

.net-core c# entity-framework expression-trees reflection

Question

Est-il possible d'automatiser ces mappages avec réflexion?

J'ai un mappage de colonne simple:

var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>
{
    ["id"] = v => v.Id,
    ["name"] = v => v.Name,
    ["isActive"] = v => v.IsActive
};

résultat d'exécution de columnsMap:

entrez la description de l'image ici


Je veux automatiser ces mappages dans une classe wrapper:

 public class QueryColumnMapper<T> : Dictionary<string, Expression<Func<T, object>>>
    {
        public QueryColumnMapper<T> GenerateMappings()
        {
            foreach (var item in typeof(T).GetProperties())
            {
                // get dictionary key ======> its OK
                var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name

                // get expression    =======> this is the problem. wrong way
                Expression<Func<T, object>> exp = v => v.GetType().GetProperty(item.Name);
                //Expression<Func<T, object>> exp = v => v.?????;    <-----   

                // add to mapper object
                this.Add(name, exp);
            }
            return this;
        }
    }

exemple d'utilisation de cette classe:

var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();  

résultat d'exécution de columnsMap: entrez la description de l'image ici

Je ne sais pas s'il est possible d'obtenir mon expression de manière dynamique au moment de l'exécution

(J'utilise ce dictionnaire de mappage pour appliquer le filtrage sur une requête IQueryable avec une entité. Avec le premier exemple (mappage manuel), il fonctionne mais je ne sais pas comment procéder de la sorte sans mappage manuel)

Réponse acceptée

Vous pouvez créer une expression personnalisée manuellement à l'aide du nom de la propriété.

// x =>
var parameter = Expression.Parameter(typeof(T));
// x.Name
var mapProperty = Expression.Property(parameter, "Name");
// (object)x.Name
var convertedExpression = Expression.Convert(mapProperty, typeof(object));
// x => (object)x.Name
var exp = Expression.Lambda<Func<T, object>>(convertedExpression, parameter);

S'il s'agit d'un sous-ensemble commun et que vous le réalisez assez souvent, vous pouvez créer une interface de base.


Réponse populaire

pour les autres spectateurs, j'ai partagé le code final:

 public class QueryColumnMapper<T> 
{
    public QueryColumnMapper()
    {
        Mappings = new Dictionary<string, Expression<Func<T, object>>>();
    }
    public Dictionary<string, Expression<Func<T, object>>> Mappings { get; set; }
    public Dictionary<string, Expression<Func<T, object>>> GenerateMappings()
    {
        foreach (var item in typeof(T).GetProperties())
        {
            var name = Char.ToLowerInvariant(item.Name[0]) + item.Name.Substring(1); //camel-case name

            // add to mapper object
            Mappings.Add(name, GetExpression(item.Name));
        }
        return Mappings;
    }

    private Expression<Func<T,object>> GetExpression(string propertyName)
    {
        // x =>
        var parameter = Expression.Parameter(typeof(T));
        // x.Name
        var mapProperty = Expression.Property(parameter, propertyName);
        // (object)x.Name
        var convertedExpression = Expression.Convert(mapProperty, typeof(object));
        // x => (object)x.Name
        return Expression.Lambda<Func<T, object>>(convertedExpression, parameter);
    }
}

usage:

var columnsMap = new QueryColumnMapper<Industry>().GenerateMappings();



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi