Pregunta

Tengo una clase con un montón de propiedades que se ven así:

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

Sería mucho más fácil si pudiera confiar en C# 3.0 para generar el almacén de respaldo para estos, pero ¿hay alguna forma de factorizar IsDirty=true;para poder escribir mis propiedades de esta manera y seguir teniendo el mismo comportamiento:

[MakesDirty]
public string Name { get; set; }
¿Fue útil?

Solución

No.No sin escribir considerablemente más código (¿arcano?) que la versión original. (Tendrías que usar la reflexión para verificar el atributo en la propiedad y demás...¿Mencioné que es 'más lento')?Este es el tipo de duplicación con la que puedo vivir.

La EM tiene la misma necesidad de generar eventos cuando se cambia una propiedad.INotifyPropertyChanged es una interfaz vital para las notificaciones de cambios.Cada implementación que he visto todavía lo hace

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

Si fuera posible, me imagino que esos chicos inteligentes de MS ya tendrían algo así implementado...

Otros consejos

Podrías intentar configurar un fragmento de código para que sea más fácil crearlos.

Si realmente quieres ir por ese camino, modificar lo que hace el código usando un atributo, hay algunas formas de hacerlo y todas están relacionadas con AOP (programación orientada a aspectos).Verificar PostSharp, que es un postcompilador que puede modificar su código en un paso posterior a la compilación.Por ejemplo, podría configurar un atributo personalizado para sus propiedades (o aspecto, como se llama en AOP) que inyecte código dentro de los establecedores de propiedades, que marque sus objetos como sucios.Si desea algunos ejemplos de cómo se logra esto, puede consultar su tutoriales.

Pero tenga cuidado con AOP porque con la misma facilidad puede crear más problemas al usarlo que está tratando de resolver si no se usa correctamente.

Hay más marcos AOP, algunos usan postcompilación y otros usan mecanismos de interceptación de métodos que están presentes en .Net; estos últimos tienen algunos inconvenientes de rendimiento en comparación con los primeros.

No, cuando usas propiedades automáticas no tienes ningún control sobre la implementación.La mejor opción es utilizar una herramienta de creación de plantillas, fragmentos de código o crear un SetValue privado.<T>(ref T backingField, valor T) que encapsula la lógica del configurador.

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}

La otra alternativa podría ser un generador de código como Codesmith para automatizar la creación de propiedades.Esto sería especialmente útil si las propiedades que está creando son columnas en una tabla de base de datos.

Puedo recomendar usar Biblioteca empresarial para ese propósito.Policy Application Block ofrece la infraestructura para hacer "algo" (algo = puedes codificarlo por tu cuenta) cada vez que ingresas o sales de un método, por ejemplo.Puedes controlar el comportamiento con atributos.Tómelo como una pista y entre en detalles con la documentación de la biblioteca empresarial.

Hay un DefaultValueAttribute que se puede asignar a una propiedad; lo utilizan principalmente las herramientas de diseño para que puedan indicar cuándo se ha cambiado una propiedad, pero podría ser una forma "ordenada" de describir cuál es el valor predeterminado de una propiedad. , y así poder identificar si ha cambiado.

Necesitaría usar Reflection para identificar cambios de propiedad, lo cual en realidad no es así. eso ¡Caro a menos que estés haciendo mucho!

Advertencia:No podría saber si una propiedad se había cambiado ATRÁS de un valor no predeterminado al predeterminado.

Yo diría que la mejor manera de resolver esto es utilizar la programación orientada a aspectos (AOP).Mats Helander hizo un escribe sobre esto en InfoQ.El artículo es un poco complicado, pero es posible seguirlo.Hay varios productos diferentes que realizan AOP en el espacio .NET; recomiendo PostSharp.

Si opta por los Atributos, estoy bastante seguro de que tendrá que rueda tu propia lógica deducir lo que significan y qué hacer al respecto.Cualquier cosa que esté utilizando sus objetos de clase personalizados tendrá que tener una forma de realizar estas acciones/verificaciones de atributos, preferiblemente en la creación de instancias.

De lo contrario, estás considerando usar quizás eventos.Aún tendría que agregar el evento a cada método set, pero el beneficio sería que no estaría codificando qué hacer con los conjuntos sucios en cada propiedad y podría controlar, en un solo lugar, lo que se debe hacer.Eso introduciría, como mínimo, un poco más de reutilización de código.

Objeto vinculado al contexto.Si crea una clase que extiende el objeto vinculado al contexto y crea un ContextAttribute, puede interceptar las llamadas realizadas a dicha propiedad y establecer IsDirty..NET creará un proxy para su clase para que todas las llamadas pasen por algo así como un receptor remoto.

Sin embargo, el problema con este enfoque es que su proxy sólo será invocado cuando se le llame externamente.Te daré un ejemplo.

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

Cuando se llama a la propiedad1 desde otra clase, se invocará su proxy.Pero si otra clase llama a la propiedad2, aunque el conjunto de propiedad2 llamará a la propiedad1, no se invocará ningún proxy (no es necesario un proxy cuando estás en la clase misma).

Hay una gran cantidad de código de muestra sobre el uso de ContextBoundObjects, búsquelo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top