Freitag, 29. Juni 2012

A flexible way for validation in Silverlight

There are numerous ways to do validation in Silverlight. Plenty of blog posts have been written about all of them, so I will just provide a list with links and then I will focus on the approach I implemented recently.


Binding property Mechanism Description
ValidatesOnExceptions Exceptions
  • Easy to implement
  • Synchronous
  • Only one error per property at a time.
ValidatesOnDataErrors IDataErrorInfo
  • Must not throw exception in property setter
  • Synchronous
  • Only one error per property at a time
ValidatesOnNotifyDataErrorInfo INotifyOnDataErrorInfo
  • Supports asynchronous validation
  • Can deliver multiple properties at a time
  • Enabled in Binding by default
Data Annotations Attributes
  • Easy to implement
  • Multiple validation rules per property

The INotifyOnDataErrorInfo approach provides the most flexibility. The fact that it is enabled by default saves you a lot of time in case you have a lot of views currently not using any validation rules. But the implementation of the interface seems like a lot of work. So I started thinking about how to make things easy.

How things should work

My idea was to write validation code like this:

    public String Description
    {
      get
      {
        return Get(() => Description);
      }
      set
      {
        Set(() => Description, value);
      }
    }

    public IEnumerable<ValidationError> Validate_Description()
    {
      if (Description.Length < 20)
        yield return new ValidationError("Description is too short.");
    }

The Get() / Set() methods are described in our view model base class. I wanted to use tha same aproach for validation as we use for executing commands through methods prefixed with Execute_.

How to get things to work

The wohle magic happens in the view model base class. This is the one to implement the INotifyOnDateErrorInfo interface:

public abstract class ViewModelBase :  INotifyPropertyChanged, INotifyDataErrorInfo
{
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public virtual bool HasErrors
    {
      get { return Get(() => HasErrors); }
      set { Set(() => HasErrors, value); }
    }


    public IEnumerable GetErrors(string propertyName)
    {
      
    }

    protected virtual void OnValidationChanged(String PropertyName)
    {
      if (ErrorsChanged != null)
        ErrorsChanged(this, new DataErrorsChangedEventArgs(PropertyName));
    }
}

In the constructor of the class we scan for methods that start with the prefix Validate_ to create validation rules for them. To do so, we define an interface IValidationRule and a class RelayValidator - very similar to the ICommand / RelayCommand implementation:

public interface IValidationRule
{
  IEnumerable<ValidationError> GetValidationErrors(Object Value);
}

public class RelayValdiator : IValidationRule
{
  private Func<object, IEnumerable<ValidationError>> ValidateFunction;
  
  public RelayValdiator(Func<Object, IEnumerable<ValidationError>> Validator)
  {
    this.ValidateFunction = Validator;
  }

  public IEnumerable<ValidationError> GetValidationErrors(Object Value)
  {
    return ValidateFunction(Value);
  }
}

The object parameter passed to the GetValidationErrors method is the property value to be validated. Now we can build up a Dictionary<String, List<IValidationRule>> containing the property name as key and a list of validation rules for the property (as I wanted to be able to have multiple validation rules later).

var ValidateMethodNames = 
  this.GetType().GetMethods()
      .Where(m => m.Name.StartsWith(VALIDATE_PREFIX))
      .Select(m => m.Name.StripLeft(VALIDATE_PREFIX.Length));

var result = ValidateMethodNames
      .ToDictionary(
        name => name, 
        name => new List<IValidationRule>() 
        { 
          new RelayValdiator(x => GetValidationErrors(name, x)) 
        }
      );

The function GetValidationErrors is defined in the base class as well:

private IEnumerable<ValidationError> GetValidationErrors(
                                                   String PropertyName, Object PropertyValue)
  {
    var validateMethodInfo = ViewModel.GetType().GetMethod(VALIDATE_PREFIX + PropertyName);
    if (validateMethodInfo == null)
      return null;

    return (IEnumerable<ValidationError>)
            validateMethodInfo.Invoke(ViewModel, 
            validateMethodInfo.GetParameters().Length == 1 ? new[] { PropertyValue } : null);
    }

The method takes the passed in method name, looks up the method in the class via reflection and invokes it. One little trick is done here anyway: the Validate_Description method as shown above does not take a parameter, as we do not need it in the view model where we can access the value directly. So we see wether we have a parameter and if not, we just do not pass it.

With this in place, we can easily implement the GetErrors method, where m_ValidationRules is the above constructed dictionary.

public IEnumerable GetErrors(string propertyName)
{
  if (propertyName.IsNullOrEmpty())
    return null;

  if (m_ValidateionRules == null)
    return null;

  if (!m_ValidateionRules.ContainsKey(propertyName))
    return null;

  var rules = m_ValidateionRules[propertyName];
  var result = rules.SelectMany(r => r.GetValidationErrors(Get<Object>(propertyName)))
                    .Select(e => new ValidationError(propertyName, e.ErrorMessage));

  // Update HasErrors property

  return result;
}

As mentioned before, the Get<Object>(propertyName) method is part of the view model and delivers the value of a property given its name. It is based on a dictionary as well.

The one thing we missed so far is the HasErrors property. Of course we want it to be set automatically according to the validation errors. So we introduce a list of property names with properties being in an errenous state. Each time we encounter an error we add the name to the list, otherwise we remove it. So if the list contains any element HasErrors must be true, if it is empty it must be false. This is done by the following code, to be inserted in the above listing at the comment:

var propertyHasErrors = result != null && result.Count() > 0;

if (propertyHasErrors)
  if (!m_ErrorProperties.Contains(propertyName))
    m_ErrorProperties.Add(propertyName);
else
  m_ErrorProperties.Remove(propertyName));

HasErrors = m_ErrorProperties.Count != 0;

Further steps

In the first place there is quite some code to write to get things working. But once you have it, you can do some other neat things. For example you can define attributes for validation:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class IsNotNullValidation : Attribute, IValidationRule
{
  public IEnumerable<ValidationError> GetValidationErrors(object Value)
  {
    var StringValue = Value as String;

    if (StringValue != null && StringValue.IsNullOrEmpty())
    {
      yield return new ValidationError("Der Wert darf nicht leer sein.");
    }

    if (Value == null)
      yield return new ValidationError("Der Wert darf nicht leer sein.");
  }
}

You can stack them on top of your properties. The only thing to do is to not only scan for perfixed methods but for attributes as well and add them to your dictionary.

Happy validating!

Dienstag, 26. Juni 2012

Be careful with (optional) params[]

I just came across an issue with the C# params keyword. It allows you to pass an arbitrary number of arguments to function. Within the funciton the parameters are available as an array which might as well be empty.

The original signature looked like this:
public String GetFormattedMessage(int messageId, params object[] placeholderValues)
{...}

The method looked up the message with the given id in a database. The message might contain placeholder, in which the passed values must be inserted. Because a message can have any number of placeholders, they are passed as params-array (yes, the method handles the case of having to much / to less parameters as well :-))


Calls to the method looked like this:
// The operation {0} succeeded
var msg = GetFormattedMessage(4711, "load customers");
// Customer with first name {0} and last name {1} not found
var msg = GetFormattedMessage(4712, "John", "Smith");
// No service listenting on port {0}
var msg = GetFormattedMessage(4713, 8881);


The new requirement was to be able to hand in a default messagse in case the given message id could not be found, for example due to a missing database update.


So the new signature was:

public String GetFormattedMessage(int messageId, string defaultMessage, params object[] placeholderValues)
{...}

Here comes the problem with the overloaded method: the first two of the above calls immediatly started to call the new overload with the default message. In all cases, and these are the majority, where the first placeholder argument was a string, the second overload is called because the string placholder value is best to fit with the string defaultMessage parameter.

I could not find a nice solution for that. Here were the two options I considered:

  • Introduce a new type for the string defaultMessage parameter like so:
    public String GetFormattedMessage(int messageId, DefaultMessage defaultMessage, params object[] placeholderValues)
  • Do not overload but introduce a new method with a distinct name:
    public String GetFormattedMessageWithDefault(int messageId, string defaultMessage, params object[] placeholderValues)
I have choosen option two because it seemed more explicit to me. I am not happy with that but could not think of another solution - if anyone has thoughts about it, I would be glad to hear. If not, you may keep it in mind to avoid such a situation. At best avoid optinal parameters anyway.

Happy coding!

Freitag, 15. Juni 2012

A better world with a better switch statement

It is known that using switch statements should, in most cases, be replaced by polymorphism when using object oriented languages (refer to Clean Code by Robert Martin, Code Smell G23).

But you must stay pragmatic as well, and sometimes the switch statement is an option. But: why must it's C# syntax look like this? Why is it so inconsistant with the rest of the language? Why do we have to write break?

I imagine a switch-statement like this:

switch (selector)
{
  case (value)
  { ... }

  case (other value || still other value)
  { ... }

  case (new List<>() { a, b, c })
  { ... }

  default 
  { ... }
}

So no ':' that reminds me of lables. No break after each case - use the well known block delimiter instead. Write the argument to the case keyword in braces as like with if, while, for and others. Do not stack control structures but use known logical operators / lists to combine cases.

Would this not be nice?



Mittwoch, 13. Juni 2012

Get hold of the view in the view model

The Problem


Triggered by a tweet from Vaughn Vernon about the question on how to get a reference to the view in a view model I decided to post the solution I used for this.

In general it is not a good practice though, but I needed it sometime as well (mostly because of some part of the system that was not designed with MVVM in mind).

The Solution


I defined an interface for the view and let the view implement it. The interface contains a a reference to the view model through an interface. The view model resides in the views DataContext so we route the property to this:

public interface IView
{ 
  IViewModel ViewModel { get; set; }
}

public partial class View : UserControl, IView
{ 
  public IViewModel ViewModel 
  { 
    get { return DataContext as IViewModel; }
    set { this.DataContext = value; } 
  }
}

The interface for the view model contains a reference to the view through its interface.

public interface IViewModel
{ 
    IView View { get; set; }
}

public class ViewModel : VMBase, IViewModel
{ 
    public IView View { get; set; }
}

Now in the XAML of the view I wire up the view model

<UserControl>
    <UserControl.DataContext>
        <local:ViewModel />
    </UserControl.DataContext>
</UserControl>

In the loaded-event of the view I set the reference back to the view model:

public void Control_Loaded(Object sender, EventArgs e)
{
  if (ViewModel != null)
    ViewModel.View = this;
}

And thats it.

What I like about this solution is that your view / view model know each other only by means of an interface, which gives you a certain amount of decoupling. But it is quite a bit of additional code...

The Drawbacks

As I mentioned earlier it is generally not a good practice to try to do this. Mostly it points to the fact that the system is not MVVMable - but sometimes reality knocks at the door...
A problem with this apporach is timing. If you need the view reference say in the constructor of your view model you wont be successful with the above technique. But you can use it in commands or any time after the view was loaded which was always sufficient for me.
Finally I don't claim that this is a general purpose solution to all cases one might want to use this - it is just what did the job for me.

Maybe it might be helpful to someone else...





Dienstag, 5. Juni 2012

Unit Testing and static methods

Miško knew since 2008 what I stumbled about today: you have a hard time if you try to test things using static classes / members.

My case was similiar to this one:

public static class SomeFactory
{
  public ISomeObject Create() { // do nasty things such as service calls }
}

public class ThisIsWhatIWantToTest
{
  public void AMethod()
  {
    // ...
    var someObject = SomeFactory.Create();
    // ...
  }
}


I wanted to write tests for AMethod but I had a hard time. Acutally I could not manage to find a seam to work around the service call easily.

Another thing I noticed along the way is, that static things obscure the dependencies in the code. This is not a good thing because it makes the code harder to understand. If you have dependencies, the should be widely visible for the sake of clarity.

I will very carefully consider the use of statics from now.

Cheers,
Tobias.

Montag, 4. Juni 2012

Incremental Builds with TFS

A very handy TFS feature is kind of well hidden in the settings. The setting is so "tiny" that I did not find it for a long time. But first things first.

The task: set up a team build that compiles only those assemblies that have been modified since the last build. You can call this an incremental build.

The whole magic is the "Clean Workspace" parameter in the build definitions process tab. Here one can choose how the build handles its workspace. You have three choices:

  1. All: Delete Sources & Binaries, then get all and build all. This is a complete rebuild. This is the default
  2. Outputs: Delete the binaries but keep the sources. Gets only the sources that have changed (incremental get). Recompiles all the sources so you get a full set of binaries.
  3. None: Delete nothing. Gets only the sources that have changed and rebuilds only assemblies that have changed. 

Option three is the one that does the trick. If you trigger a build, than change something and trigger another build, your drop location will hold two folders. You will see all the files in both folders but dont be disappointed. All files are moved to the drop location, but mind the changed date: they are all different.


This way you can figure out easily what has acutally changed. This comes in handy if you want to ship hotfixes that only contain files that have really changed to keep installing the hotfix quick.

Have a nice build ;-)
Tobias.