Pages

Wednesday, 26 November 2008

WCF and Custom Exceptions

From within the Server we throw custom exceptions which contain custom data that the client code can use. To transport these across WCF to the client we wrap them in a FaultException like this:
catch (BlockBookingInvalidFloorsException ex)
{
throw new FaultException(ex);
}
Despite the fact that both the custom exception and the contained classes are marked as [Serializable()] it results in a WCF CommunicationException.

To resolve this we now add this new constructor:
public BlockBookingInvalidFloorsException(SerializationInfo serializationInfo, StreamingContext streamingContext)
: base(serializationInfo, streamingContext) { }
Martin found this blog with a fuller explanation: WCF and Custom Exceptions

Claus suggests that custom exceptions should derive from either CommunicationException or System.Exception. Our's derive from ApplicationException with no problem, indeed the ApplicationException already includes this constructor (protected).

Sub Classing Window and UserControl

I wanted to add a standard method (InjectModel) into our Windows and UserControls and the obvious technique was to subclass them with something like this:
public partial class PersonEditView : WindowBase
{
...
}

public class WindowBase : Window
{
...
}
The xaml then needs to reference the WindowBase class like this:
<local:WindowBase x:Class="INPC2.PersonEditView"
...
xmlns:local="clr-namespace:INPC2"
>
<local:WindowBase.Resources>
...
</local:WindowBase.Resources>
...
</local:WindowBase>
There is no problem with the forward reference to xmlns:local

ObjectDataProvider

To make UI design easier in Blend we want to provide dummy data at design time. Using an ObjectDataProvider with an ObjectType attribute achieves this (provided the bound datasource can provide dummy data).

<ObjectDataProvider x:Key="DesignTimeDataProvider" d:IsDataSource="True" ObjectType="{x:Type Dummy_Application:PeopleDataProvider}"/>
However it is not possible to replace the ObjectType with an ObjectInstance at runtime.
We got round that problem by using two ObjectDataProviders:
<ObjectDataProvider x:Key="DesignTimeDataProvider" d:IsDataSource="True" ObjectType="{x:Type Dummy_Application:PeopleDataProvider}"/>
<ObjectDataProvider x:Key="InnerDataProvider" d:IsDataSource="true" ObjectInstance="{StaticResource DesignTimeDataProvider}"/>
<ListBox ItemsSource="{Binding Path=DataProvider.PeopleList, Source={StaticResource InnerDataProvider}}"/>
Then in the code behind we replace the ObjectInstance with our freshly minted data source:
ObjectDataProvider odpWindow = (ObjectDataProvider)this.FindResource("InnerDataProvider");
odpWindow.ObjectInstance= newPeopleDataProvider;
The problem with this approach is that at runtime a datasource is created (as part of InitializeComponent) that is then immediately discarded.

To resolve this I created my own ObjectDataProvider which nulls the ObjectType at runtime. This is enough to allow the ODP to accept a change to the ObjectInstance without complaint.
public class MyObjectDataProvider : ObjectDataProvider
{
bool isInDesignMode = (bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue;
public new Type ObjectType
{
get { return base.ObjectType; }
set
{
if (!isInDesignMode) value = null;
base.ObjectType = value;
}
}
}

public partial class PersonEditView : Window
{
public PersonEditView()
{
InitializeComponent();
((ObjectDataProvider)this.FindResource("DataModel")).ObjectInstance = model; }
}
The xaml then becomes simpler and cleaner:
<local:MyObjectDataProvider x:Key="DataModel" d:IsDataSource="True" ObjectType="{x:Type local:PersonEditModel}" />
<TextBlock Text="{Binding Source={StaticResource DataModel}, Path=APerson.Surname}"/>

INotifyPropertyChanged

I had a conversation with Martin about INotifyPropertyChanged and it made me realise there was an (other) aspect of Binding that I hadn't appreciated.

So I created a little project to test my assumptions.

1) Business Class implements INotifyPropertyChanged

public class Person : INotifyPropertyChanged
{
private string _surname = "";
public string Surname
{
get { return _surname; }
set
{
_surname = value;
OnPropertyChanged("Surname");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2) Model exposing two instances of Person. Model does not implement INPC

public class Model
{
public Person APerson { get; set; }
public Person AnotherPerson { get; set; }
public Model()
{
APerson = new Person();
AnotherPerson = new Person();
}
}
3) Bind to only one of the two instances of Person in the Model

<TextBlock Text="{Binding Model.APerson.Surname}"></TextBlock>
<Button Click="Button_Click">Go</Button>
4) Wire it all up

public partial class Window2 : Window
{
private Model _model = new Model();
public Model Model
{
get { return _model; }
set { _model = value; }
}
public Window2()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Model.APerson.Surname = "Smith";
Model.AnotherPerson.Surname = "Jones";
}
}
Result:
PropertyChanged is only hooked up for APerson and not for AnotherPerson because nothing is bound to AnotherPerson in the xaml.

Conclusion:
I might need to revisit the changes I made to AbstractModel hooking up PropertyChanged and DataError. Currently they are hooked up when the Model is instantiated, regardless of whether there is any binding in the xaml.

Quiz - guess the technology

Jeremiah says:
I've been vocal at work about how stupid I think xxxxxx is.

Mike says:
Why is it stupid?

Jeremiah says:
Because it looks snazzy 4 seconds after you've put in a feature but then 4 months later it still isn't quite right; takes forever to make minor tweaks; doesn't have anything to offer over simple HTML (other than the RAD) but has less features.

Wednesday, 19 November 2008

Custom Control Part 2

In "Custom Control Part 1" we created a raw custom control that does nothing. In this post we'll change the control so it only does "one thing" - stores its original value and when the current value differs it sets the HasChanged property to true.

This needs a couple of private member vars (OldText & Initialised) to hold the state, a new DependencyProperty (HasChangedProperty), a standard CLR property (HasChanged) and some logic added to the TextPropertyChanged event handler.

public class DemoTextBox : TextBox
{
static DemoTextBox()
{
// Create a callback for when the TextProperty changes
PropertyChangedCallback callback = new PropertyChangedCallback(TextPropertyChanged);

// Override the TextProperty metadata in order to link up the callback routine
TextProperty.OverrideMetadata(
typeof(DemoTextBox),
new FrameworkPropertyMetadata(callback));
}
static void TextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
// Cast the Sender to an object of this class
DemoTextBox textBox = (DemoTextBox)sender;
 

// Store the OldText value when this event is
// fired for the first time
 
if (!textBox.Initialised)
{
textBox.Initialised = true;
textBox.OldText = textBox.Text;
}

// Set the HasChangedProperty to indicate whether the text has changed

textBox.SetValue(HasChangedProperty, (textBox.OldText != textBox.Text));

 
}

 
private bool Initialised = false;
private string OldText = "";
 
// The new DependencyProperty
 
static readonly DependencyProperty HasChangedProperty = DependencyProperty.Register(
"HasChanged",
typeof(bool),
typeof(DemoTextBox)
);
 
// The new CLR Property
 
public bool HasChanged
{
get { return (bool)GetValue(HasChangedProperty); }
}

}

In the Generic.xaml we'll add a Trigger to turn the textbox background Red when the Text value has changed.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp">
<Style TargetType="{x:Type local:DemoTextBox}">
<Style.Triggers>

<Trigger Property="HasChanged" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>

</Style.Triggers>
</Style>
</ResourceDictionary>

Tuesday, 18 November 2008

Custom Control Part 1

I've struggled to find a really simple example of creating a custom control. So I created a simple control that did only "one thing" then removed the "one thing" to leave just the very least plumbing that I could.

Starting with a new class that inherits from TextBox:
public class DemoTextBox : TextBox
{
static DemoTextBox()
{
// Create a callback for when the TextProperty changes
PropertyChangedCallback callback = new PropertyChangedCallback(TextPropertyChanged);
// Override the TextProperty metadata in order to link up the callback routine
TextProperty.OverrideMetadata(
typeof(DemoTextBox),
new FrameworkPropertyMetadata(callback));
}
static void TextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
// Cast the Sender to an object of this class
DemoTextBox textBox = (DemoTextBox)sender;

}
}

Add a ResourceDictionary called Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp>
<Style TargetType="{x:Type local:DemoTextBox}">
<Style.Triggers>
<!-- create a trigger here -->
</Style.Triggers>
</Style>
</ResourceDictionary>

And a reference to the new control in the Window:
<Window x:Class="DepProp.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepProp"
Title="Window2" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary Source="Generic.xaml"/>
</Window.Resources>
<StackPanel>
<local:DemoTextBox x:Name="TextBoxV1" Text="Original Value" />
</StackPanel>
</Window>

ActiveSharp and StackTrace speed

When implementing the StackTrace within ActiveSharp I did a few tests to check out the speed of the different techniques I could use to get the Property Name.

All the following times are for one million iterations.

TechniqueMilliseconds
ActiveSharp400
StackWalk120000
MethodBase.GetCurrentMethod()2000
"string"20
const string10

The speed of ActiveSharp is a little unrealistic because it caches the Property Name for each field in the class. A class with more properties or accessing many different objects would reduce the speed advantage.

Since the StackWalk was so slow I decided to check whether it was my code (examining the stack) or the creation of the stack in the first instance.
private void Button_Click_2(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000000; i++)
{
StackTrace trace = new StackTrace();
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}
One million iterations took 118,000 milliseconds to complete. There is little point trying to improve my code further.

MultiBinding

I stumbled across MultiBinding today. I have no immediate use for it but I mustn't forget that it is available.

There is a nice simple example from MSDN here: MultiBinding Class

Monday, 17 November 2008

ActiveSharp

ActiveSharp is an excellent piece of free software (ActiveSharp Home Page) written by John Rusk to implement the INotifyPropertyChanged interface.

Since we already have a abstract class that implements INPC I simply used the PropertyMap.GetProperty(this, ref target) method to get the property name and avoid having to hardcode the name as a string in each Property.

I ran into a slight problem because we have some classes that expose the same field in multiple properties (not necessarily the right thing to do but that's what we've got) and ActiveSharp can't deal with this situation.

My proposed solution was to change ActiveSharp to walk the Stack when it encountered these duplicates. John was kind enough to explain the potential pitfalls and the alternative technique of using marking all Properties with this attribute:
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

The primary issue is around "inlining" methods when the Release code is built. This can result in fewer entries being available on the stack. Therefore a modified GetProperty might work during development but not live.

I read that there are some situations that prevent inlining:

  • Methods that are greater than 32 bytes of IL will not be inlined.

  • Virtual functions are not inlined.

  • Methods that have complex flow control will not be in-lined. Complex flow control is any flow control other than if/then/else; in this case, switch or while.

  • Methods that contain exception-handling blocks are not inlined, though methods that throw exceptions are still candidates for inlining.

  • If any of the method's formal arguments are structs, the method will not be inlined.

A little experimentation showed that marking the SetValue and GetValue methods in my abstract base class as virtual was enough to get a consistent stack in both Debug and Release versions.

For now this appears to be working OK but I might need to revisit when we move to 64bit Windows Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks

Important Note:Running the Release version from within the IDE does not give the same results as running the application as a standalone .exe

Speed of Exceptions

I wanted to check for duplicates as entries were being added to my Dictionary collection. I wasn't sure whether to use ContainsKey and check each and every time an item is added or simply sweep up after the Add method throws an Exception.

In reality the best solution will depend on the likely hit rate of duplicates but I thought I'd write the following code to test the speed differential when the hit rate is 100%.

Using ContainsKey
private void Button_Click(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000; i++)
{
if (dummy.ContainsKey("Sunday"))
{
dummy["Sunday"]++;
}
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}

Using Exceptions
private void Button_Click_1(object sender, RoutedEventArgs e)
{
DateTime start = DateTime.Now;
for (int i = 0; i <= 1000; i++)
{
try
{
dummy.Add("Sunday", 7);
}
catch
{
dummy["Sunday"]++;
}
}
DateTime end = DateTime.Now;
MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
}

Results
Using ContainsKey: 2 milliseconds
Using Exceptions: 5338 milliseconds

The ContainsKey adds about 0.04 milliseconds for the 1000 iterations - the rest is the down to the increment of the Dictionary int value.

Monday, 3 November 2008

DelegateCommand vs RoutedCommand vs EventHandler

I wanted to evaluate the difference between using the different types of Command mechanisms. The following code snippets aren't intended to be a working example, they simply highlight the code differences.


DelegateCommand
SimplePresenter.cs

public DelegateCommand<string> GetCustomerByDC { get; private set; }

GetCustomerByDC = new DelegateCommand(ExecuteGetCustomer, CanExecuteGetCustomer);

private void ExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
GetCustomer(customerId);
}
catch { }
}
}
private bool CanExecuteGetCustomer(string parameter)
{
try
{
int customerId = int.Parse(parameter);
return true;
}
catch
{
return false;
}
}

SimpleView.xaml.cs
ObjectDataProvider odpPresenter = (ObjectDataProvider)this.FindResource("MyPresenter");
Presenter = (SimplePresenter)odpPresenter.ObjectInstance;
Presenter.Model = newModel as SimpleModel;
Presenter.View = this;
private void txtCustomerId_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
Presenter.GetCustomerByDC.RaiseCanExecuteChanged();
}

SimpleView.xaml

xmlns:Presenters="clr-namespace:Sandstorm.Documents.Patterns.Presenters"
<ObjectDataProvider x:Key="MyPresenter" d:IsDataSource="True" ObjectType="{x:Type Presenters:SimplePresenter}"/>
<Button
x:Name="btnGetByDC"
Command="{Binding Source={StaticResource MyPresenter}, Path=GetCustomerByDC}"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By DelegateCommand</Button>
<TextBox
TextChanged="txtCustomerId_TextChanged"
/>

RoutedCommand

SimpleView.xaml.cs
private void GetCustomer_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
if (e.Parameter != null)
{
try
{
int customerId = int.Parse(e.Parameter as string);
Presenter.GetCustomer(customerId);
}
catch { }
}
}
private void GetCustomer_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
try
{
int customerId = int.Parse(e.Parameter as string);
e.CanExecute = true;
}
catch
{
e.CanExecute = false;
}
}

SimpleView.xaml
<UserControl.CommandBindings>
<CommandBinding
Command="local:LeisureCommands.GetCustomerCommand"
Executed="GetCustomer_Executed"
CanExecute="GetCustomer_CanExecute"
/>
</UserControl.CommandBindings>
<Button
x:Name="btnGetByRC"
Command="local:LeisureCommands.GetCustomerCommand"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Routed Command</Button>

LeisureCommands.cs
public class LeisureCommands : RoutedUICommand
{
public readonly static RoutedUICommand GetCustomerCommand;
static LeisureCommands()
{
GetCustomerCommand = new RoutedUICommand("Get Customer...", "GetCustomerCommand", typeof(LeisureCommands));
GetCustomerCommand.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
}
}



Event
SimpleView.xaml.cs
private void btnGetByClick_Click(object sender, RoutedEventArgs e)
{
try
{
int customerId = int.Parse(txtCustomerId.Text);
Presenter.GetCustomer(customerId);
}
catch { }
}

SimpleView.xaml
<Button
x:Name="btnGetByClick"
Click="btnGetByClick_Click"
CommandParameter="{Binding ElementName=txtCustomerId, Path=Text}"
Width="170"
>Get By Click Event</Button>


Lines of code
TypeRawOneOffPer CommandCan ExecuteTotal
DelegateCommand406341222
RoutedCommand457381226
Event15015n/a15


Conclusion
The RoutedCommand is a little more expensive in LOC terms than the DelegateCommand but the DelegateCommand does not support all the features of the RoutedCommand, in particular: Gestures.
If the "CanExecute" facility is not required the Event is by far the cheapest / easiest to implement.
I guess my conclusion was: "What are the DelegateCommands bringing to the party?"