Obtenir le nom et la valeur de PropertyInfo

c# dynamic expression-trees reflection typedescriptor

Question

J'ai déjà vu différentes manières de le faire, notamment la réflexion, les descripteurs de type de modèle de composant, les arbres d'expression et les aspects, MAIS je ne suis toujours pas sûr que le code ci-dessous atteigne tous les objectifs suivants en utilisant .Net 4.0 ou supérieur:

  1. Soyez sûrs de votre texte, amicalement pour les refacteurs (sans ficelle magique) et lisibles
  2. Maximiser les performances sur plusieurs appels
  3. Fournir le nom d'une propriété
  4. Fournir la valeur de la propriété

Comment le code peut-il être amélioré?

protected void NotifyOfPropertyChanging<TProperty>(Expression<Func<TProperty>> property) {
    var memberExpression = (MemberExpression)property.Body;
    var prop = (PropertyInfo) memberExpression.Member;

    var propertyName = prop.Name;
    var value = prop.GetValue(this, null);

    // fire INPC using propertyName
    // use value and name to do IsDirty checking
}

Réponse acceptée

Vous pourrez peut- être améliorer les performances en compilant l'arborescence des expressions et en la mettant en cache pour une utilisation ultérieure au lieu d'appeler GetValue chaque fois. Cependant, de telles optimisations ne doivent être effectuées que si votre implémentation actuelle provoque un goulot d'étranglement.

void NotifyOfPropertyChanging<TProperty>(Expression<Func<TProperty>> property)
{
    var memberExpression = (MemberExpression) property.Body;
    var prop = (PropertyInfo) memberExpression.Member;

    Func<TProperty> accessor;
    if (!TypedAccessorCache<TProperty>.Cache.TryGetValue(prop, out accessor))
    {
        accessor = property.Compile();
        TypedAccessorCache<TProperty>.Cache[prop] = accessor;
    }
    var value = accessor();

    // ...
}

static class TypedAccessorCache<TProperty>
{
    public static readonly IDictionary<PropertyInfo, Func<TProperty>> Cache =
        new Dictionary<PropertyInfo, Func<TProperty>>();
}

Notez que j'ai utilisé un type statique générique pour contenir l'instance du dictionnaire de cache. C'est un moyen pratique de créer efficacement un cache typé distinct pour chaque type de propriété distinct.


Réponse populaire

C'est une longue histoire et je suppose qu'il n'y a toujours pas d'approche unique meilleure que les autres. Je pense que les expressions ne feront pas baisser les performances dans la plupart des scénarios commerciaux habituels (et que vous pouvez optimiser ultérieurement un petit morceau de code nécessitant des notifications plus rapides si vous en avez besoin), cette approche devrait donc être correcte.

Gardez simplement à l'esprit que la création d'un arbre d'expression prend beaucoup plus de temps que son analyse, assurez-vous donc que vous ne le faites qu'une seule fois (c'est-à-dire en utilisant des variables d'expression statiques au niveau de la classe). Cependant, votre code de modèle devient un peu gonflé dans ce cas.

Personnellement, je préfère utiliser la gestion INPC basée sur des chaînes. ReSharper fonctionne bien avec les chaînes lorsqu'il s'agit de refactoriser, je peux donc l'appeler relativement sûr. Pour autant que je sache, c'est l'approche la plus rapide. Et en utilisant des extraits VS ou ReSharper, vous pouvez facilement écrire vos propriétés en plusieurs frappes.

En ce qui concerne la valeur de la propriété, elle n'est utilisée ni par INotifyPropertyChanging ni par l'interface INotifyPropertyChanged . Pourquoi en avez-vous besoin?



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