Obtención de PropertyInfo Nombre y valor

c# dynamic expression-trees reflection typedescriptor

Pregunta

He visto varias formas de hacer esto, incluida la reflexión, los descriptores de tipo de modelo de componente, los árboles de expresión y los aspectos, PERO aún no estoy seguro de si el código siguiente logra todos los siguientes objetivos con .Net 4.0 o superior:

  1. Sea seguro, refactor amigable (sin cadenas mágicas) y legible
  2. Maximiza el rendimiento en múltiples llamadas
  3. Proporcione el nombre de una propiedad
  4. Proporcionar el valor de la propiedad.

¿Cómo se puede mejorar el código?

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
}

Respuesta aceptada

Es posible que pueda mejorar el rendimiento compilando el árbol de expresiones y almacenándolo en caché para su uso futuro en lugar de llamar a GetValue cada vez. Sin embargo, dichas optimizaciones solo deben realizarse si su implementación actual provoca un cuello de botella.

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>>();
}

Note que he usado un tipo estático genérico para mantener la instancia del diccionario de caché. Esta es una forma práctica de crear efectivamente un caché escrito por separado para cada tipo de propiedad diferente.


Respuesta popular

Es una larga historia y creo que todavía no existe un enfoque único que sea mejor que otros. Creo que las expresiones no harán que el rendimiento se vea afectado en la mayoría de los escenarios comerciales habituales (y puede optimizar un pequeño fragmento de código que necesita notificaciones más rápidas si es que lo necesita), por lo que este enfoque debería ser correcto.

Solo tenga en cuenta que crear un árbol de expresiones requiere mucho más tiempo que analizarlo, así que asegúrese de hacerlo solo una vez (es decir, mediante el uso de variables de expresión estáticas de nivel de clase). Sin embargo, su código de modelo se hincha un poco en ese caso.

Personalmente prefiero usar el manejo de INPC basado en cadenas. ReSharper funciona bien con cuerdas cuando se trata de refactorizar, por lo que puedo decir que es relativamente seguro. Por lo que sé, este es el enfoque más rápido. Y utilizando los fragmentos de código VS o ReSharper, puede escribir fácilmente sus propiedades con varias pulsaciones de tecla.

Con respecto al valor de la propiedad, no se usa ni por INotifyPropertyChanging ni por la interfaz INotifyPropertyChanged . ¿Por qué lo necesitas?



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow