Esto es en respuesta a un comentario que dejé . Espero que esto responda a tu pregunta, Shimmy. Solo comente, y lo acortaré o eliminaré si no responde su pregunta.
Necesitará las interfaces INotifyPropertyChanging e INotifyPropertyChanged para ser implementadas en su clase (a menos que sea algo así como un objeto de entidad de marco, que creo que implementa estos internamente).
Y antes de establecer un valor para esta propiedad, deberá elevar el evento NotifyPropertyChanging.PropertyChanging, utilizando el nombre de la propiedad en el constructor PropertyChangingEventArgs.
Y después de establecer este valor, debe subir el evento NofityPropertyChanged.PropertyChanged, nuevamente utilizando el nombre de la propiedad que se está generando en el constructor PropertyChangedEventArgs.
entonces usted tiene que controlar los eventos PropertyChanging y PropertyChanged. En el evento PropertyChanging, debe almacenar en caché el valor. En el evento PropertyChanged, puede comparar y lanzar una excepción.
para obtener la propiedad del evento args PropertyChanging/PropertyChanged, es necesario utilizar relfection.
// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it checks if e.PropertyName already exists.
propertyDict.Add(e.PropertyName, propertyValue);
} // End PropertyChanging() Event
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it makes sure e.PropertyName exists.
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
// No longer needed.
propertyDict.Remove(e.PropertyName);
if (/* some condition */)
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
} // End try
} // End if
} // End PropertyChanging() Event
Observe cómo estoy usando PreventRecursion, que es un valor lógico me olvidó añadir por encima de estos métodos? Cuando restablece la propiedad a su valor anterior, estos eventos serán recuperados.
tl; dr
Ahora se podría derivar un solo evento que hereda de INotifyPropertyChanged, pero utiliza un argumento que sostiene un objeto que representa el valor anterior, así como el nombre de la propiedad.Y eso reduciría la cantidad de eventos activados a uno, tiene una funcionalidad similar y tiene compatibilidad con INotifyPropertyChanged.
Pero si quiere manejar algo antes de que se establezca la propiedad (digamos que la propiedad hace un cambio irreversible o necesita configurar otras propiedades antes de establecer esa variable, de lo contrario se lanzará una excepción) no podrá Haz eso.
En general, este método es una forma muy antigua de hacer las cosas. Tomaría la respuesta de Poker Villian y podría ingresar datos inválidos. Pero no permite guardar en una base de datos.
Entity Framework tiene un código excelente para la validación. Usted agrega validación a sus propiedades a través de atributos. Y luego se encarga del trabajo de procesar esos atributos. Luego puede crear una propiedad llamada IsValid, que llama a la validación específica de Entity Framework. También distingue los errores de campo (como escribir los caracteres incorrectos o tener una cadena demasiado larga) y los errores de clase (como tener datos faltantes o claves conflictivas).
A continuación, puede vincular IsValid a la validación de controles, y se mostrará una burbuja roja mientras se ingresan datos no válidos. O simplemente podría implementar la validación de IsValid usted mismo. Pero si IsValid es falso, el evento SaveChanges necesitaría cancelar el guardado.
btw. El código proporcionado no se compilará y solo es un pseudocódigo (mezclando vb y C#). Pero creo que es mucho más descriptivo que C# solo, mostrando exactamente lo que se está manejando.
PropertyChangingEventArgs no tiene ninguna relación con CancelEventArgs. Tienen tiempos que necesitan ser utilizados exclusivamente para diferentes propósitos. Forzar la herencia causaría complicación y frustración innecesarias (unirlas estrechamente). Hay PropertyChangingEvent y PropertyChangedEvent, y creo que satisfacen la funcionalidad que usted desea sin que se le hagan cambios (sin mencionar que rompería la compatibilidad de .NET 1.1 con .NET 4.0). – TamusJRoyce
@TamusJRoyce, OK, estoy de acuerdo, no debería heredar de 'CancelEventArgs', pero lo que debería hacer es mi otra solicitud que proporciona el valor candidato (que la manera más fácil de conseguirlo es obtener los atributos de método actuales con un significado significativo cantidad de costo de rendimiento). – Shimmy