2017-04-09 2 views
1

Comment refactoriser ce code C# en une méthode générique GetBy(string property, string search)?Comment refactoriser cela en Expression générique?

public MyModel GetByName(string name) 
    { 
     return GetAll().SingleOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase)); 
    } 

    public MyModel GetByUrl(string url) 
    { 
     return GetAll().SingleOrDefault(d => string.Equals(d.Url, url, StringComparison.OrdinalIgnoreCase)); 
    } 

GetAll() donne retour Liste des MyModel, donc cela peut être un problème aussi, ce n'est pas un résultat IQueryable.

+1

Sachez que si vous faites cela, vous perdrez tout type sûr ty, c'est généralement une mauvaise idée ... – DavidG

+1

Que diriez-vous de 'public MyModel Get (Expression > propriété, valeur)' de sorte que vous pouvez vous assurer que les appelants ne transmettent qu'une propriété valide? ou omettez l'expression si vous avez déjà une liste en mémoire. –

Répondre

3

Vous pourriez mais ce n'est pas un bon moyen de maintenir la sécurité de type. Sinon, vous pouvez le faire comme ça:

public MyModel GetBy<T>(Func<MyModel, T> property, T value) where T : IEquatable<T> { 
     return GetAll().SingleOrDefault(d => property(d).Equals(value)); 
    } 

GetBy(m => m.Name, "Foo"); 

Ou:

public MyModel GetBy(Func<MyModel, bool> predicate) { 
       return GetAll().SingleOrDefault(predicate); 
      } 

GetBy(m => m.Name.Equals("Foo", StringComparison.OrdinalIgnoreCase)); 
+0

Je voudrais ajouter à la première solution peut-être dans le cas typeof (T) == typeof (chaîne) le paramètre de comparaison de chaîne ... – MBoros

+0

Je choisis la seconde. Merci beaucoup! – martonx

-1

Vous pouvez simplement appeler les méthodes existantes

public MyModel GetBy(string property, string search) 
{ 
    switch (property) { 
     case nameof(MyModel.Name): 
      return GetByName(search); 
     case nameof(MyModel.Url): 
      return GetByUrl(search); 
     default: 
      throw new ArgumentException($"Unsupported property \"{property}\""); 
    } 
} 

Et bien sûr, vous pouvez inline ces deux fonctions. Mais pourquoi l'appeler GetAll au lieu de Set<MyModel>?

+0

Cela ressemble à un peu un hack, et je * pense * OP veut que la méthode soit générique afin qu'elle puisse fonctionner pour n'importe quelle propriété, bien que ce soit une supposition. – DavidG

+0

J'utilise GetAll parce qu'il y a une certaine logique derrière GetAll, et pas seulement DbSet. – martonx

0

aide de la réflexion on peut en fin de se lier à la propriété désirée:

public MyModel GetBy(string name, string value) 
    { 
     var getter = typeof(MyModel).GetProperty(name).GetGetMethod(); 
     return GetAll().SingleOrDefault(d => 
      string.Equals(getter.Invoke(d, null).ToString(), value, StringComparison.OrdinalIgnoreCase)); 
    } 

(qui précède suppose la la propriété nommée existe toujours et n'est jamais nulle)