Introduction
We are going to add two numbers using Constructor Injection and then display their sum in a Silverlight XAML page. To use Constructor Injection, we are going to use the Unity Container.
Background
Before reading this article, some knowledge on Dependency Injection will be an added advantage. Unity Application Block 1.2 for Silverlight has been used in the code that is attached to this article.
Using the Code
To understand how Unity works in this sample, we first need to understand what we depend on when we are adding two numbers and generating a total (any guesses?). Yup, the total, in fact, depends on the numbers that are being added together (obvious, I suppose!).
The two numbers that are going to be added are represented as interfaces in the sample code. It makes more sense for these numbers to be implemented this way in the sample to properly showcase Constructor Injection.
Let us begin by looking at how a number is represented in this sample code. We are using an interface and then implementing this interface in a number class. The second number is also implemented in a similar fashion.
public interface INumberA {
int NumA {get;set;}
}
public class NumberA:INumberA {
private int intNumA;
public int NumA
{
get {return intNumA;}
set { intNumA = value; }
}
}
Next, we move on to the Total
class. This class has a constructor that takes two parameters as numbers and assigns each one of them to private class variables. We will see what NumA
and NumB
are just after this.
public Total(INumberA objA, INumberB objB)
{
this.objA = objA;
this.objB = objB;
NumA = 0;
NumB = 0;
}
The Total
class will also implement the INotifyPropertyChanged
interface. Since we bind NumA
, NumB
, and Sum
to textboxes in our XAML, these properties have to raise change events (via OnPropertyChanged
in this sample).
public int Sum {
get {
return intSum;
}
set {
if (intSum != value) {
intSum = value;
OnPropertyChanged("Sum");
}
}
}
public int NumA {
get {
return objA.NumA;
}
set {
if (objA.NumA != value) {
objA.NumA = value;
OnPropertyChanged("NumA");
GetSum();
}
}
}
public int NumB {
get {
return objB.NumB;
}
set {
if (objB.NumB != value) {
objB.NumB = value;
OnPropertyChanged("NumB");
GetSum();
}
}
}
The GetSum
method is where the actual number totaling occurs.
private void GetSum()
{
Sum = objA.NumA + objB.NumB;
}
Moving on to the XAML file (in this case, Page.xaml). It has some text box controls aligned inside a grid. These text boxes are primarily responsible for displaying the two numbers and their sum total. I won't delve into the XAML layout in this sample.
<textbox x:name="num1" text="{Binding Mode=TwoWay, Path=NumA}"
maxlength="4" grid.column="0" grid.row="1"
fontweight="Normal" fontsize="14"
verticalalignment="Center" horizontalalignment="Center" />
<textbox text="+" maxlength="1" grid.column="1"
grid.row="1" fontweight="Normal" fontsize="14"
verticalalignment="Center" horizontalalignment="Center"
isreadonly="True" />
<textbox x:name="num2" text="{Binding Mode=TwoWay, Path=NumB}"
maxlength="4" grid.column="2" grid.row="1"
fontweight="Normal" fontsize="14"
verticalalignment="Center" horizontalalignment="Center" />
<button type="button" width="30" grid.column="3"
grid.row="1" verticalalignment="Bottom"
content="=" height="30">
<textbox x:name="txtBlock" text="{Binding Sum}"
maxlength="6" grid.column="4" grid.row="1"
fontweight="Normal" fontsize="14" verticalalignment="Center"
horizontalalignment="Center" isreadonly="True"/>
Now, most importantly, if we look at the XAML code-behind file, we see the following code inside the method that executes when the page has been loaded.
private void Page_Loaded(object sender, RoutedEventArgs e) {
IUnityContainer container = new UnityContainer();
container.RegisterType<INumberA,NumberA>();
container.RegisterType<INumberB,NumberB>();
this.DataContext = container.Resolve<Total>();
}
We create an instance of the Unity Container. This instance will be responsible for instantiating all classes which it finds are dependencies for the Total
class to be instantiated. So, when we say container.Resolve<Total>()
, the Total
class and all its underlying dependency classes defined in the constructor (i.e., NumberA
and NumberB
) are instantiated.
In addition to Resolve
, we also need to register our number interfaces with their concrete implementations (using RegisterType
). Thus, this provides capabilities to delay our decisions to use a particular class till runtime in a loosely coupled manner.
In this sample, every time a number is entered in one of the text boxes and the 'equal to' command button is clicked on, the total is calculated and displayed.
Points of Interest
This sample uses OneWay binding for the Sum
property, but TwoWay binding for the two number properties. This allows us to update our sum without really using any code in the button click event handler. Every time text is changed inside one of the text boxes and they lose focus, the underlying source is updated.
History
- Initial revision - 30th May, 2009.