Copying an object in C# and Visual Basic


Sometimes there are classes you find you use in every project. I remember once (shudder) I, rather inelegantly instantiated a class, and performed a manual copy of all the properties in the object (when the pressure was on, and I just needed to make the thing work).

I have also found myself spending hours chasing subtle and hard to debug issues where ICloneable has been used -  which, incidentally, is widely accepted as an interface one ought never use – or Object.MemberwiseClone. It turns out the only way to do this correctly, is to serialise the object, and then use the deserialised object, implemented here using an extension method.

Even though this is quite straightforward, I still am posting this however , because I find I need to use this functionality frequently, and often I no longer have access to the source, or it takes ages to find the class. The Visual Basic code sample is after the C# one.

C#

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
 
namespace ObjectCopierApp.Extensions
{
/// <summary>
/// Provides a method for performing deep copying of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
internal static class ObjectCopier
{
/// <summary>
/// Perform a deep copy of an object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
internal static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
 
// Don’t serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null))
{
return default(T);
}
 
IFormatter formatter = new BinaryFormatter();
 
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
}
 
 

Visual Basic

Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
 
Namespace ObjectCopierApp.Extensions
”’ <summary>
”’ Provides a method for performing deep copying of an object.
”’ Binary Serialization is used to perform the copy.
”’ </summary>
Friend NotInheritable Class ObjectCopier
Private Sub New()
End Sub
”’ <summary>
”’ Perform a deep copy of an object.
”’ </summary>
”’ <typeparam name="T">The type of object being copied.</typeparam>
”’ <param name="source">The object instance to copy.</param>
”’ <returns>The copied object.</returns>
<System.Runtime.CompilerServices.Extension()> _
Friend Shared Function Clone(Of T)(source As T) As T
If Not GetType(T).IsSerializable Then
Throw New ArgumentException("The type must be serializable.", "source")
End If
 
‘ Don’t serialize a null object, simply return the default for that object
If ReferenceEquals(source, Nothing) Then
Return Nothing
End If
 
Dim formatter As IFormatter = New BinaryFormatter()
 
Using stream = New MemoryStream()
formatter.Serialize(stream, source)
stream.Seek(0, SeekOrigin.Begin)
Return DirectCast(formatter.Deserialize(stream), T)
End Using
End Function
End Class
End Namespace

Calculate range/limit with C#


A recurring requirement in every day programming is determining whether a value exists with a certain range. Since it is exam time (for most students at present), I resolved to write a quick application demonstrating this requirement based around examination marks.

This quick demo is written in WPF, but should work in Silverlight or Windows Phone 7 with no alteration. The Range class though, can be used throughout .NET in general.

To start with, create a new WPF application in visual Studio and call it ExamApp. Add a new folder to the project called Range and in this declare a new interface called IRange with the following members

using System;
 
namespace ExamApp.Range
{
public interface IRange<T> where T : IComparable<T>
{
T Start { get; }
T End { get; }
bool InRange(T valueToFind);
}
}

Create a new class in the same folder called Range which implements the interface above

using System;
 
namespace ExamApp.Range
{
public class Range<T> : IRange<T> where T : IComparable<T>
{
private readonly T start;
private readonly T end;
 
public Range(T start, T end)
{
if (start.CompareTo(end) <= 0)
{
this.start = start;
this.end = end;
}
else
{
this.start = end;
this.end = start;
}
}
 
public T Start
{
get { return this.start; }
}
 
public T End
{
get { return this.end; }
}
 
public bool InRange(T valueToFind)
{
return valueToFind.CompareTo(Start) >= 0 && valueToFind.CompareTo(End) <= 0;
}
}
}
 

Add a new Folder to the project called Examinations and in this add a new class called Percentage. This Percentage class inherits off Range, and here you can create whatever logical range class you may desire for your own applications

using System;

using ExamApp.Range;
 
namespace ExamApp.Examinations
{
public class Percentage<T> : Range<T> where T : IComparable<T>
{
public Percentage(T start, T end) : base(start, end)
{
}
}
}
 

Add a new enumeration called Grade thus

namespace ExamApp.Examinations

{
public enum Grade
{
None = 0,
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
} ;
}
 

Add a new interface called ITest with the following members.

namespace ExamApp.Examinations

{
interface ITest
{
int ArtAndDesignMark { get; set; }
int ScienceMark { get; set; }
int MathsMark { get; set; }
}
}
 

Add a new folder called Converters to the project, and add the following

using System;

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
using System.Windows.Markup;
using ExamApp.Examinations;
 
namespace ExamApp.Converters
{
public class MarkToGradeConverter : MarkupExtension, IValueConverter
{
private static MarkToGradeConverter instance;
private static readonly Dictionary<Percentage<int>, Grade> Marks;
 
static MarkToGradeConverter()
{
Marks = new Dictionary<Percentage<int>, Grade>
{
{new Percentage<int>(80, 100), Grade.A},
{new Percentage<int>(75, 79), Grade.B},
{new Percentage<int>(60, 74), Grade.C},
{new Percentage<int>(55, 59), Grade.D},
{new Percentage<int>(0, 54), Grade.E},
};
}
 
public override object ProvideValue(IServiceProvider serviceProvider)
{
return instance ?? (instance = new MarkToGradeConverter());
}
 
#region Implementation of IValueConverter
 
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return GetGrade((int)value).ToString();
}
 
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
public static Grade GetGrade(int mark)
{
Percentage<int> key = Marks.Keys.FirstOrDefault(r => r.InRange(mark));
 
if (key != null)
{
Grade grade;
 
if (Marks.TryGetValue(key, out grade))
{
return grade;
}
}
return Grade.None;
}
 
#endregion
}
}
 

As you can see most of the logic is executed here. Add a new class to the project called Student with the following properties. Also note that this implements the ITest interface that was declared earlier

using ExamApp.Examinations;

 
namespace ExamApp
{
public class Student : ITest
{
public Student(string firstName, string surname, int artAndDesignMark, int scienceMark, int mathsMark)
{
this.FirstName = firstName;
this.Surname = surname;
this.ArtAndDesignMark = artAndDesignMark;
this.ScienceMark = scienceMark;
this.MathsMark = mathsMark;
}
 
public Student()
{
}
 
public string FirstName { get; set; }
public string Surname { get; set; }
 
#region Implementation of ITest
 
public int ArtAndDesignMark { get; set; }
public int ScienceMark { get; set; }
public int MathsMark { get; set; }
 
#endregion
 
}
}
 

We need a collection of students to show in a list so create the following class that inherits off ObservableCollection<T>

using System.Collections.ObjectModel;

namespace ExamApp
{
public class Students : ObservableCollection<Student>
{
public Students()
{
Add(new Student
{
FirstName = "John",
Surname = "Lennon",
ArtAndDesignMark = 81,
ScienceMark = 59,
MathsMark = 77
});
Add(new Student
{
FirstName = "Paul",
Surname = "McCartney",
ArtAndDesignMark = 88,
ScienceMark = 40,
MathsMark = 66
});
Add(new Student
{
FirstName = "Ringo",
Surname = "Starr",
ArtAndDesignMark = 88,
ScienceMark = 31,
MathsMark = 96
});
Add(new Student
{
FirstName = "George",
Surname = "Harrison",
ArtAndDesignMark = 100,
ScienceMark = 99,
MathsMark = 99
});
 
}
}
}
 

Now the data structures are complete, add the following .xaml markup

<Window x:Class="ExamApp.MainWindow"
xmlns:Converters="clr-namespace:ExamApp.Converters"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<Converters:MarkToGradeConverter x:Key="MarkToGradeConverter" />
</Window.Resources>
<ListView x:Name="studentsListBox">
<ListView.View>
<GridView>
<GridViewColumn Width="120"
DisplayMemberBinding="{Binding Path=FirstName}"
Header="Name" />
<GridViewColumn Width="120"
DisplayMemberBinding="{Binding Path=Surname}"
Header="Surname" />
<GridViewColumn Width="40"
DisplayMemberBinding="{Binding Path=ArtAndDesignMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Art" />
<GridViewColumn Width="60"
DisplayMemberBinding="{Binding Path=ScienceMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Science" />
<GridViewColumn Width="50"
DisplayMemberBinding="{Binding Path=MathsMark,
Converter={StaticResource MarkToGradeConverter}}"
Header="Maths" />
</GridView>
</ListView.View>
 
</ListView>
 
</Window>
 

Add the following code to the constructor of the main window

using System.Windows;
 
namespace ExamApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.studentsListBox.ItemsSource = new Students();
}
}
}
 

You should have the following

Students

As you can see it is quite a simple and pretty reusable way to use ranges in your application.

The source code for this simple example is available here

Zoomable autosizing canvas in WPF


I have created a control for a project I am working on that uses a canvas to draw graph ticks for a custom scale, but ran into the limitation of the canvas control where child items are not scaled accordingly when the height (or width) of the canvas changes. Luckily, this is quite a straightforward problem to fix, but I just could not seem to find either the correct search terms to enter in Google or locating code samples in books that demonstrated how to resolve the issue. I have just knocked this code up this afternoon so it is not perfect, but should suffice should you require something similar.

Small

Large

In order to resolve the problem you will need to create a custom canvas and override both MeasureOverride and ArrangeOveride incorporating any custom logic you require in these methods.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
 
namespace AutosizingCanvasApp.Controls
{
public class TickCanvas : Canvas
{
// Vertical axis where the X value is never changed
private const double X = 0;
private Size initialSize;
 
// Override the default Measure method of Panel
protected override Size MeasureOverride(Size availableSize)
{
var canvasDesiredSize = new Size();
 
// In our example, we just have one child.
// Report that our canvas requires just the size of its only child.
 
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
canvasDesiredSize = child.DesiredSize;
}
 
return canvasDesiredSize;
}
 
protected override Size ArrangeOverride(Size finalSize)
{
if (initialSize.Height == 0)
{
initialSize = finalSize;
}
var ratio = finalSize.Height / initialSize.Height;
 
for (int index = 0; index < this.InternalChildren.Count; index++)
{
UIElement child = this.InternalChildren[index];
 
double y = ((Line)child).Y1;
 
child.Arrange(finalSize.Height > initialSize.Height
? new Rect(new Point(X, (ratio * y) – y), child.DesiredSize)
: new Rect(new Point(X, 0), child.DesiredSize));
}
return finalSize; // Returns the final Arranged size
}
}
}

In the .xaml I have a border with the custom canvas as a child that have some Line objects all affecting the Y axis position.

<Window x:Class="AutosizingCanvasApp.MainWindow"
xmlns:controls="clr-namespace:AutosizingCanvasApp.Controls"
xmlns:local="clr-namespace:AutosizingCanvasApp.Converters"
Title="mainWindow"
Width="300"
Height="768"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<local:BorderHeightValueConverter x:Key="BorderHeightValueConverter" />
<local:LinePositionConverter x:Key="LinePositionConverter" />
</Window.Resources>
 
<Border x:Name="mainBorder"
Width="94"
Height="{Binding ElementName=mainWindow,
Path=ActualHeight,
Converter={StaticResource BorderHeightValueConverter}}"
Margin="50"
BorderBrush="Black"
BorderThickness="2"
ToolTip="{Binding ElementName=mainBorder,
Path=ActualHeight}">
<controls:TickCanvas x:Name="myCanvas">
<Line x:Name="line1"
Stroke="Red"
StrokeThickness="2"
ToolTip="{Binding ElementName=line1,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.2}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.2}" />
<Line x:Name="line2"
Stroke="Blue"
StrokeThickness="2"
ToolTip="{Binding ElementName=line2,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.4}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.4}" />
<Line x:Name="line3"
Stroke="Green"
StrokeThickness="2"
ToolTip="{Binding ElementName=line3,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.6}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.6}" />
<Line x:Name="line4"
Stroke="Purple"
StrokeThickness="2"
ToolTip="{Binding ElementName=line4,
Path=Y1}"
X1="0"
X2="60"
Y1="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.8}"
Y2="{Binding ElementName=mainBorder,
Path=ActualHeight,
Converter={StaticResource LinePositionConverter},
ConverterParameter=0.8}" />
</controls:TickCanvas>
</Border>
</Window>

I also have a couple of converters that converts the height of the border as that changes when you resize the parent window and a couple of converters that reposition the line objects in the canvas. Be aware that the border itself has a thickness, so you will need to incorporate that in any sizing but has been omitted here so the lines may be a couple of pixels off.

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace AutosizingCanvasApp.Converters
{
public class LinePositionConverter : IValueConverter
{
#region Implementation of IValueConverter
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double) value)*double.Parse(parameter.ToString());
}
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
#endregion
}
}

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace AutosizingCanvasApp.Converters
{
public class BorderHeightValueConverter : IValueConverter
{
#region Implementation of IValueConverter
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (((double)value)*0.7);
}
 
/// <summary>
/// Converts a value.
/// </summary>
/// <returns>
/// A converted value. If the method returns null, the valid null value is used.
/// </returns>
/// <param name="value">The value that is produced by the binding target.</param><param name="targetType">The type to convert to.</param><param name="parameter">The converter parameter to use.</param><param name="culture">The culture to use in the converter.</param>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
 
#endregion
}
}
 

The source code is for this example is available here.

Windows Phone 7 – The Real Game Changer


 

Excitation

I am really exited in the direction Microsoft has taken with Windows Presentation Foundation and Silverlight, in that they have really demonstrated that they see these two technologies as the future of their user interface based aspects in their software by making significant investment in the technology. For a start, they have used WPF to great effect in Visual Studio 2010. Frequently, I spend 10 to 12 hours in Visual Studio and it is an absolute joy to use the 2010 version as the previous user interface that had not changed for a decade was showing its age. The number of enhancements in Visual Studio is plethoric, and includes automatically generated UML diagrams all done in WPF, but that really is another subject in itself.

A brief history

I decided to move the focus of my development over a year ago to WPF after spending a number of years in Windows Forms, before that it had been Delphi, before that C/C++ and domain specific languages primarily used in the medical, banking and defence industries. It was a bit of a gamble, because if you live outside of London (I am in Manchester), then WPF jobs are few and far between, as most business that required investment in software to gain the competitive edge has already done so. The opportunities with WPF and Silverlight usually arise in start-ups, of which I am involved in one at present. The exciting thing is not being tied to a codebase that is many years old, with a license to use the latest and greatest software. I moved the project I was working on to .NET 4.0 the day it was released, without needing endless meetings deliberating about the why, that what and the what for. It is beginning to look as the gamble I took has paid off, as I have overnight become a Windows Phone 7 developer. This included being a Silverlight developer as well.

Windows Phone 7

I, like many people use my mobile phone daily, and cannot imagine what it would be like not to have a mobile phone. I have been a little sceptical about the real usefulness of iPhone applications, as most of them presented themselves as bubblegum to me. Taste sweet for five minutes, then endlessly insipid afterwards. I have also been put off by having to learn objective C and the Apple implementation. The only Apple product I have owned was a G4 some years ago, but it ended up unused as it was not suited to the kind of development I needed to do at the time. My current mobile phone contact is up in a months time, I had resigned myself to getting an iPhone, simply because it is one of the best phones on the market, with a breadth of applications, something my current phone lacks.

I watched the announcement at Mix for the Windows Phone 7 with glee, and with the leaked images of a Dell phone (courtesy of Engadget) I resolved that I would have to wait till Christmas using my current phone as I had become a Windows Phone developer overnight

04-21-10lightningg4

Tools

I would say the chief issue that determines whether I do something or not now is how long it will take me. My time is very limited, so anything that requires a steep learning curve without a significant return of investment for that time usually means that I won’t look twice at it. this is also true for Microsoft release CTP’s so frequently it can be hard to keep up. I decided to download the CTP for Windows Phone 7, as a release that integrates with Visual Studio 2010 RTM has now been made available here. The installation was quick and polished enough to give me the confidence that it should not break my Visual Studio  installation. What you get is a version of Visual Studio Express (seems to me only C# at the moment, so I hope a Visual Basic version is available or is in the pipeline) that included the following template (also installed into Visual Studio 2010)

30-04-2010 08-49-09

After choosing the Windows Phone Application you get what looks more like a WPF application rather than a Silverlight application

30-04-2010 08-55-36

Press F5 and you get an emulator for the phone that contains a working version of Internet Explorer and the eye catching transitions between pages

30-04-2010 09-01-51

looking at the nuts and bolts of the thing, they are using the Navigation pattern that is so familiar to me, it seems like I am writing a WPF application. I will dig deeper into how one can leverage their existing skills to create a simple application for Windows Phone 7