2008-09-15 42 views
5

que tienen una clase con un grupo de propiedades que se parecen a esto:C# propiedades con código repetido

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

Sería mucho más fácil si pudiera depender de C# 3.0 para generar el almacén de respaldo para estos, pero ¿hay alguna forma de factorizar el IsDirty = verdadero? de modo que pueda escribir mi propiedades algo como esto y aún así obtener el mismo comportamiento:

[MakesDirty] 
public string Name { get; set; } 
+0

Parece que esto no es posible (gracias Gishu), así que voy a utilizar las plantillas de CodeRush para esto. Gracias por recordarme sobre los fragmentos. –

Respuesta

5

No. No sin necesidad de escribir código mucho más (arcano?) Que la versión original (Habría que utilizar la reflexión para comprobar si el atributo de la propiedad y lo que no .. ¿le he dicho que sea 'más lenta ') .. Este es el tipo de duplicación con la que puedo vivir.

MS tiene la misma necesidad para raising events when a property is changed. INotifyPropertyChanged que es una interfaz vital para las notificaciones de cambio. Cada aplicación que he visto hasta ahora hace

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

Si fuera posible, me gustaría averiguar esos tipos inteligentes en la EM ya habría algo por el estilo en su lugar ..

3

Usted podría intentar la creación de un fragmento de código para hacer más fácil para crear esos.

0

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

0

objeto ContextBound. Si crea una clase que amplía el objeto vinculado al contexto y crea un atributo de contexto, puede interceptar las llamadas realizadas a dicha propiedad y establecer IsDirty. .NET creará un proxy para su clase, de modo que todas las llamadas superen algo así como un receptor remoto.

El problema con este enfoque es que su proxy solo se invocará cuando se llame externamente. Te daré un ejemplo.

clase A { [Foo] public int Propiedad1 {get; establecer;} public int Propiedad2 {get {return variable;} set {Property1 = value; variable = valor; }

}

Cuando propiedad1 se le llama de otra clase, su proxy sería si invoked.But otra clase llama propiedad2, aunque el conjunto de propiedad2 será poner en propiedad1 será invocado sin proxy, (un proxy no es necesario cuando estás en la clase en sí).

Hay una gran cantidad de código de muestra de usar contextboundobjects, míralo.

+0

Amir, esto técnicamente es una solución; sin embargo, personalmente, no creo que este sea un buen lugar para aplicar esto :) Buena respuesta, sin embargo, no puedo expresarlo en el contexto de esta pregunta. Perdón por el juego de palabras también :) – Gishu

0

puedo recomendar a utilizar Enterprise Library para ese propósito. Policy Application Block ofrece la infraestructura para hacer "algo" (algo = usted puede codificar eso por su cuenta) cada vez que ingresa/sale 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.

0

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

Debería usar Reflection para identificar los cambios de propiedad, que en realidad no es que es caro a menos que lo haga en gran cantidad.

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

2

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

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); 
    } 
} 
+0

Pero entonces tendrías que duplicar el método SetValue en cada clase. Si lo convierte en un método público estático/de utilidad, debería exponer el estado IsDirty ... No es genial :) – Gishu

+0

@Gishu: Sí, duplicaría la llamada a SetValue en cada propiedad y posiblemente en cada clase. Dependiendo de cómo se derivan tus cálculos, determinará si SetValue (y, en consecuencia, IsDirty) es público. –

+0

Esto no funciona: http://connect.microsoft.com/VisualStudio/feedback/details/304501/operator-cannot-be-applied-to-operands-of-type-t-and-t – NotMe

0

Yo diría que la mejor manera de resolver esto es utilizar Aspect-Oriented Programming (AOP). Mats Helander hizo un write up on this on InfoQ. El artículo es un poco complicado, pero es posible seguirlo. Hay varios productos diferentes que hacen AOP en el espacio .NET, recomiendo PostSharp.

0

Si va con Atributos, estoy bastante seguro de que tendrá que roll your own logic para deducir lo que significan y qué hacer con ellos. Cualquiera que sea el uso de sus objetos de clase personalizados tendrá que tener una forma de realizar estas acciones/verificaciones de atributos, preferiblemente en instanciación.

De lo contrario, está buscando el uso de eventos tal vez. Todavía tendría que agregar el evento a cada método de conjunto, pero el beneficio sería que no está codificando qué hacer con los conjuntos sucios en cada propiedad y puede controlar, en un lugar, lo que se debe hacer. Eso, como mínimo, introduciría un poco más de reutilización de código.

3

Si realmente quieres ir de esa manera, para modificar lo que hace el código usando un atributo, hay algunas maneras de hacerlo y todas están relacionadas con AOP (programación orientada a aspectos). Consulte PostSharp, que es un postcompilador que puede modificar su código en un paso posterior a la compilación. Por ejemplo, puede configurar un atributo personalizado para sus propiedades (o aspecto, cómo se llama en AOP) que inyecta código dentro de los ajustadores de propiedades, que marca los objetos como sucios. Si desea algunos ejemplos de cómo se logra esto, puede consultar su tutorials.

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

Hay más frameworks AOP que usan post compilación y algunos utilizan mecanismos de interceptación de métodos que están presentes en .Net, los últimos tienen algunos inconvenientes de rendimiento en comparación con el primero.

+0

postsharp es perfecto para un escenario como este! –