Validation in WPF using PostSharp/AOP
Last night I went to a excellent SADeveloper.net event about AOP with PostSharp and it had me thinking…
Granted, validation is probably not the text book example of cross cutting concerns but it does proof how PostSharp/AOP can be used…
What is AOP?
Aspect-oriented programming (AOP) is a programming paradigm that increases modularity by allowing the separation of cross-cutting concerns.
Lets assume that I want to validate the age of my employees, I could do the following in my business entity
int age;
public int Age
{
get { return age; }
set
{
if (value < 18)
throw new Exception("Value must be between 18 and 99");
if (value > 99)
throw new Exception("Value must be between 18 and 99");
age = value;
}
}Now I can “turn on” ValidateOnExceptions in my UI
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Path=Age, Mode=TwoWay,
UpdateSourceTrigger=LostFocus, NotifyOnValidationError=True, ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}" Width="50" HorizontalAlignment="Left" VerticalAlignment="Top" />
This works, but what if I want to reuse this logic to check that the compulsory HR test written by each employees score is legal (ie. between 5-25)? How can I change this code to be more reusable? Enter the world of PostSharp and AOP
I created a pretty simple attribute using PostSharp
[Serializable]
public class RangeValidator : OnMethodBoundaryAspect
{
public int Min { get; set; }
public int Max { get; set; }
public RangeValidator(int min, int max)
{
Min = min;
Max = max;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if (!eventArgs.Method.Name.StartsWith("set_"))
return;
var args = eventArgs.GetReadOnlyArgumentArray();
if (args.Count() == 0)
throw new Exception("No argument passed to set");
int value = (int)args[0];
if (value > Max)
throw new Exception("Value must be between " + Min + " and " + Max);
if (value < Min)
throw new Exception("Value must be between " + Min + " and " + Max);
base.OnEntry(eventArgs);
}
}
This is a simple example of how to use PostSharp… Ok, but how do I now use this attribute? Simple, here is my new business entity
public class Employee
{
[NotNullValidator]
[StringLengthValidator(0, 32)]
public string Name { get; set; }
[NotNullValidator]
[StringLengthValidator(0, 32)]
public string Surname { get; set; }
[RangeValidator(18, 99)]
public int Age { get; set; }
[RangeValidator(5, 25)]
public int HRTestScore { get; set; }
}
I also “created” a NotNullValidator and StringLengthValidator… This cleans up the code tremendously and it is soooo simple to use!!!
Here is my test UI
Validation is a very easy example but the possibilities doesn’t end their… You can now also create a attribute to automatically implement all the INotifyPropertyChanged stuff…
Pete Weissbrod has a excellent 2 part post about how he did exactly that (Part 1 and Part 2)
PS. The form was created using XAML Power Toys... I highly recomend you check it out, read more here!