2017-08-29 4 views
7

J'ai un Entity Framework Code Premier modèle pour lequel j'ai fait une classe générique statique qui a une méthode de recherche qui est appelée pour chaque élément dans une liste. En admettant que ce soit sur ma tête, j'ai pensé que rendre la classe statique améliorerait la clarté du code et peut-être même la performance, car il n'est pas nécessaire de créer des instances dans de nombreux endroits différents. L'objectif de tout cela est d'automatiser les propriétés qui peuvent être recherchées, exportées, etc. par l'utilisateur. La question principale est: Si MakeGenericType (...) est appelé pour chaque élément (potentiellement 1000) ayant une propriété de type référence, un type générique pour cette propriété de type référence est généré une seule fois et enregistré quelque part ou généré 1000s de fois? Le fait de signaler d'autres crimes de performance ou odeurs de code est apprécié.Est-ce que l'appel de MakeGenericType (...) plusieurs fois crée un nouveau type à chaque fois?

public static class SearchUserVisibleProperties<T> 
{ 
    private static List<PropertyInfo> userVisibleProperties { get; set; } 

    static SearchUserVisibleProperties() 
    { 
     userVisibleProperties = typeof(T).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(UserVisibleAttribute))).ToList(); 
    } 

    public static bool search(T item, string searchString) 
    { 
     foreach (PropertyInfo pInfo in userVisibleProperties) 
     { 
      object value = pInfo.GetValue(item); 
      if (value == null) 
      { 
       continue; 
      } 
      if (pInfo.PropertyType == typeof(string) || pInfo.PropertyType.IsValueType) 
      { 
       ...unrelevant string matching code... 
      } 
      else if ((bool)typeof(SearchUserVisibleProperties<>).MakeGenericType(new Type[] { value.GetType() }).InvokeMember(nameof(search), BindingFlags.InvokeMethod, null, null, new object[] { value, searchString })) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 
} 
+0

Merci pour la question! J'ai toujours supposé qu'un nouveau type est créé à chaque fois, et ajouté ma propre couche de mise en cache pour éviter cela. En fait, j'écrivais le code de la réponse avec l'espoir de voir «Faux» imprimé deux fois. Il s'avère que je peux retirer sans risque ma couche de mise en cache maintenant! – dasblinkenlight

+1

Notez que 'new Type [] {value.GetType()}' n'est pas nécessaire, car le paramètre 'typeArguments' de' MakeGenericType' est déclaré avec le mot clé 'params'. Un nouveau tableau serait créé de toute façon, mais il n'encombrerait pas votre code. – dasblinkenlight

+0

Si je retire 'nouveau type [] {value.GetType()}' 'sa jette un ArgumentException' comme classe' 'SearchUserVisibleProperties a un paramètre générique qui doit être fourni, non? Donc, pas de performance évidente/amélioration de l'odorat pour mon code? Sentant un peu de fierté après avoir assemblé cela pendant plusieurs heures :). Merci d'avoir répondu! – Tom

Répondre

7

Documentation of MakeGenericType suggère que le type retourné pour la même association de définition du type générique et des arguments de type générique sera le même:

l'objet Type retourné par MakeGenericType est le même que l'Type obtenue par l'appel de la méthode GetType du type construit résultant ou de la méthode GetType de tout type construit qui a été créé à partir de la même définition de type générique en utilisant les mêmes arguments de type.

Voici une petite expérience pour montrer que ce qui précède est correct: