Je veux savoir s'il y a une meilleure façon (que ce que je fais actuellement) d'obtenir et de conserver une référence à une propriété dans un autre objet en utilisant seulement les noms de chaîne de l'objet et de la propriété. En particulier, existe-t-il une meilleure façon de le faire avec la nouvelle fonctionnalité dynamique de .Net 4.0?Quel est le meilleur moyen d'obtenir et de tenir la référence de la propriété par son nom dans C#
Voici ce que j'ai en ce moment.
J'ai un objet "PropertyReference<T>
" qui prend un nom d'objet et un nom de propriété dans le constructeur.
Une méthode Initialize()
utilise la réflexion pour trouver l'objet et la propriété et stocke la propriété Getter comme Action<T>
et la propriété Setter comme Func<T>
.
Quand je veux appeler réellement la propriété que je fais quelque chose comme ceci:
int x = _propertyReference.Get();
ou
_propertyReference.Set(2);
Voici mon code PropertyReference<T>
. S'il vous plaît disséquer et faire des suggestions pour l'amélioration.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml;
namespace WindowsFormsApplication2
{
public class PropertyReference<T> : IPropertyReference
{
public string ComponentName { get; set; }
public string PropertyName { get; set; }
public bool IsInitialized
{
get
{
return (_action != null && _func != null);
}
}
Action<T> _action;
Func<T> _func;
public PropertyReference() { }
public PropertyReference(string componentName, string propertyName)
{
ComponentName = componentName;
PropertyName = propertyName;
}
public void Initialize(IEntity e)
{
Object component = e.GetByName(ComponentName);
if (component == null) return;
Type t = e.GetByName(ComponentName).GetType();
PropertyInfo pi = t.GetProperty(PropertyName);
_action = (T a) => pi.SetValue(component, a, null);
_func =() => (T)pi.GetValue(component, null);
}
public void Reset()
{
_action = null;
_func = null;
}
public void Set(T value)
{
_action.Invoke(value);
}
public T Get()
{
return _func();
}
}
}
Note: Je ne peux pas utiliser la fonctionnalité « Emettre » comme je l'ai besoin de ce code pour travailler sur le nouveau Windows Phone 7 et qui ne prend pas en charge Emit.
MISE À JOUR:
juste fait quelques tests de vitesse après le remplacement:
_action = (T a) => pi.SetValue(component, a, null);
_func =() => (T)pi.GetValue(component, null);
Avec
_action = Action<T>)Delegate.CreateDelegate(typeof(Action<T>),component,pi.GetSetMethod());
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
Comme le suggère DTB ci-dessous.
Testé en effectuant 100 000 appels à la propriété Get(). Voici les résultats.
_func =() => (T)pi.GetValue(component, null)
a pris environ 200ms
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
a pris environ 10ms
énorme différence. Je ne m'y attendais pas, mais cool!
Toujours ouvert à plus d'améliorations.
Êtes-vous même certain que 'dynamic' sera disponible sur Win7 Smartphones? C'est un comportement assez sophistiqué que je ne suis pas soutenu. – LBushkin
Il n'y a pas de remède magique pour Reflection, toutes les solutions proposées l'utilisent. Y compris * dynamique *. –
Non, je ne suis pas sûr ... Je vais y jeter un coup d'oeil. –