2017-07-12 1 views
-1

Je cherche à utiliser dynamiquement CsvHelper en créant des expressions dans le code qui représentent l'accès des membres de la propriété pour un type donné.Créer une expression <Func <T, object>> à partir d'un type donné

La méthode que je suis en train de transmettre ces expressions à a la signature suivante:

public virtual CsvPropertyMap<TClass, TProperty> Map<TProperty>(Expression<Func<TClass, TProperty>> expression) 
    { 
     // 
    } 

Donc, vous le feriez normalement appeler, pour tout type donné que vous souhaitez mapper, comme celui-ci (pour un type avec un propriété appelée « StringProperty »):

mapper.Map(x => x.StringProperty); 

passage dans un lambda qui est converti en interne en une Expression<Func<T, object>>

J'ai essayé de créer cette expres sion dans le code, en utilisant Expressions. Au moment de la compilation tout fonctionne bien (en ce sens il renvoie un Expression<Func<TModel, object>>), mais lors de l'exécution, je reçois une exception "pas un accès membre". Voici le code qui prend un objet PropertyInfo représentant la propriété que je veux la carte:

private Expression<Func<TModel, object>> CreateGetterExpression(PropertyInfo propertyInfo) 
    { 
     var getter = propertyInfo.GetGetMethod(); 

     Expression<Func<TModel, object>> expression = m => getter.Invoke(m, new object[] { }); 
     return expression; 
    } 

En gros, comment puis-je construire cette expression correctement dans le code?

+2

Le type de propriété en fait 'object'? De plus, si vous avez déjà un objet 'PropertyInfo', pourquoi ne pas simplement appeler' PropertyInfo.GetValue() 'au lieu d'essayer d'invoquer la méthode getter? Aussi, quel est le point d'utiliser la réflexion ici? Sans un bon [mcve], il est difficile de voir ce que vous essayez vraiment d'accomplir et la difficulté spécifique que vous éprouvez. –

+0

Je partage les préoccupations de Peter, mais j'espère que cette question et réponse similaires ici: https://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet peut vous aider. –

Répondre

3

Juste essayer quelque chose ressemble à ceci:

public static Expression<Func<T, P>> GetGetter<T, P>(string propName) 
    { 
     var parameter = Expression.Parameter(typeof(T)); 
     var property = Expression.Property(parameter, propName); 
     return Expression.Lambda<Func<T, P>>(property, parameter); 
    } 

    public static Expression<Func<T, P>> GetGetter<T, P>(PropertyInfo propInfo) 
    { 
     var parameter = Expression.Parameter(typeof(T)); 
     var property = Expression.Property(parameter, propInfo); 
     return Expression.Lambda<Func<T, P>>(property, parameter); 
    } 

Il est par exemple des usages:

private class TestCalss 
    { 
     public int Id { get; set; } 
    } 

    private static void Main(string[] args) 
    { 
     var getter = GetGetter<TestCalss, int>(typeof(TestCalss).GetProperty("Id")).Compile(); 
     Console.WriteLine(getter(new TestCalss { Id = 16 })); 
    }