This and That

Dear Future Jamie:

DI with a private constructor

When you are doing DI with a private constructor, this syntax will not work:

            String animalTypeName = ConfigurationManager.AppSettings["animalTypeName"].ToString();
            Type animalType = Type.GetType(animalTypeName);
            IAnimal animal = (IAnimal)Activator.CreateInstance(animalType);

Instead use this syntax:

            String animalTypeName = ConfigurationManager.AppSettings["animalTypeName"].ToString();
            Type animalType = Type.GetType(animalTypeName);
            IAnimal animal = (IAnimal)FormatterServices.GetUninitializedObject(animalType);

Params Keyword

When you have a series of overloaded methods that are taking on an ever-growing number of parameters, consider using the params keyword.  For example, instead of this:

        public void NameMe(String FirstName)
        {

        }

        public void NameMe(String FirstName, String LastName)
        {

        }

        public void NameMe(String FirstName, String MiddleName, String LastName)
        {

        }

Do this:

        public void NameMe(params String[] parameters)
        {

        }

Love Current Jamie

Advertisements

RDU Code Camp

TriNug put on an awesome codecamp over the weekend.  I presented programming the Kinect.  There was about 20 people in my session (more than I expected) and we had a great time going through some of the basic (and way cool) features of the Kinect API.  I hope to see some really neat projects at future TriNug events using the Kinect.

My side deck and code samples are on TriNug’s wiki found here.

Proper Casing Of Proper Names

I was consuming an external API that was returning people’s first names.  The problem was that the names were coming back all caps (eg: “GILLIGAN”).  I wanted to convert that into the proper case (eg: “Gillian”).  In the past, I would call ToLower() of the string and then take the first character of a substring and make it Upper().  To protect myself in case there was several words in the name(eg: MARY ANN), I would also need to split on any spaces and loop through the array doing my Upper/Lower functions.  The code would look something like this:

static void WrongWay(String name)
{
    String tempWord = String.Empty;
    String firstLetter = String.Empty;
    String restOfWord = String.Empty;
    StringBuilder stringBuilder = new StringBuilder();

    String[] splitName = name.Split(' ');
    foreach (String word in splitName)
    {
        tempWord = word.ToLower();
        firstLetter = tempWord.Substring(0, 1);
        firstLetter = firstLetter.ToUpper();
        restOfWord = tempWord.Substring(1, tempWord.Length-1);
        stringBuilder.Append(firstLetter);
        stringBuilder.Append(restOfWord);
    }
    Console.WriteLine(String.Format("Was = {0} Now = {1}", name, stringBuilder.ToString()));
}

And the output looks like this:

image

I hate this solution for a couple of reasons:

  • It smells like Kludgy code
  • It is Kludgy code
  • It does not account for people with single letter names
  • It does not account for internationalism and different languages that use different glyphs

I thought to myself – there must be a better way and since Microsoft has lots of smart people, they might have done something like this already.

My first stop was the String.ToLower() overload.  I pumped in the different cultures (Current and CurrentUI):

static void WriteNames(String name)
{
    CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
    CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture;

    Console.WriteLine(String.Format("ToLower = {0}",name.ToLower()));
    Console.WriteLine(String.Format("ToUpperWithCurrentCulture = {0}", name.ToLower(currentCulture)));
    Console.WriteLine(String.Format("ToUpperWithCurrentUICulture = {0}", name.ToLower(currentUICulture)));
}

Alas, it did not work:

image

ToUpper() had the same (non) effect.

I then thought “Hey, maybe I should check MSDN or Stackoverflow”.  Sure enough, I ran into this page.  Without reading the entire page (who does that?)  I jammed in this line of code,

Console.WriteLine(String.Format("currentCulture.TextInfo.ToTitleCase using Upper = {0}", 
    currentCulture.TextInfo.ToTitleCase(name)));

but I got the same result:

image

 

I then went back and read the entire MSDN page.  I changed my code to this (note the ToLower())

Console.WriteLine(String.Format("currentCulture.TextInfo.ToTitleCase using Lower = {0}",
    currentCulture.TextInfo.ToTitleCase(name.ToLower())));

Sure enough:

image

Not only that, it works for multiple words:

image

Not only that, it handles middle initials!

image

Alas, it does not handle suffixes:

image

Still, that function gives you plenty out of the box.  I am very excited (OK, mildly excited) about this new find….

Signature Capture

I was chatting with another member of TriNug last night and we talked about the best way to capture a user’s signature.  There are some pretty good articles out there, including this one.  I dove right in with a WinForm application and a Panel control and built something like this:

image

 

Visual Studio 2010 and WinForms made this a pretty straightforward task.  First, I built up my domain model starting with the points that are captured from the Panel.MouseMove event handler (MouseEventArgs) with the e.Location of type Point.

I created a Line class that has 2 points that make up the line:

[Serializable]
public class Line
{
    public Line()
    {

    }

    public Line(Point startPoint, Point endPoint)
    {
        this.StartPoint = startPoint;
        this.EndPoint = endPoint;
    }

    public Point StartPoint { get; set; }
    public Point EndPoint { get; set; }
}

I then created a Glyph class that is a collection of those lines:

[Serializable]
public class Glyph
{
    public Glyph()
    {
        this.Lines = new List<Line>();
    }
    public List<Line> Lines { get; set; }
}

I could have called this class “letter” but each glyph may or may not be a letter – it could be several letters strung together in cursive, a part of a letter (the dot of the i), or may not be any letter (like when R2D2 signs his name.  R2D2 is a boy, right?)

Anyway, I then created a Signature class that is a collection of glyphs:

[Serializable]
public class Signature
{
    public Signature()
    {
        this.Glyphs = new List<Glyph>();
    }

    public List<Glyph> Glyphs { get; set; }
}

If this was used in a real-world application, this class would have a uniqueId so you can relate it back to your people/user class.  It might have some other properties to allow easy comparison and analysis.

I then coded in my WinForm a way to capture the user’s mouse strokes and putting them into this signature graph.  First, I started with some form level variables:

Boolean IsCapturing = false;
private Point startPoint;
private Point endPoint;
Pen pen = new Pen(Color.Black);
Glyph glyph = null;
Signature signature = new Signature();
String fileName = @"signature.xml";

I then handled three events from the panel:

private void SignaturePanel_MouseMove(object sender, MouseEventArgs e)
{
    if (IsCapturing)
    {
        if (startPoint.IsEmpty && endPoint.IsEmpty)
        {
            endPoint = e.Location;
        }
        else
        {
            startPoint = endPoint;
            endPoint = e.Location;
            Line line = new Line(startPoint, endPoint);
            glyph.Lines.Add(line);
            DrawLine(line);
        }

    }
}
private void SignaturePanel_MouseUp(object sender, MouseEventArgs e)
{
    IsCapturing = false;
    signature.Glyphs.Add(glyph);
    startPoint = new Point();
    endPoint = new Point();

}

private void SignaturePanel_MouseDown(object sender, MouseEventArgs e)
{
    IsCapturing = true;
    glyph = new Glyph();
}

Basically, every time a user clicks down it starts capturing the points and turning them into lines.  When the user clicks up, all of those lines go into 1 glyph.  Capture…Rinse….Repeat.

There is 1 supporting function (DrawLine) that looks like this to render it to the screen:

private void DrawLine(Line line)
{
    using (Graphics graphic = this.SignaturePanel.CreateGraphics())
    {
        graphic.DrawLine(pen, line.StartPoint, line.EndPoint);
    }
}

A couple of notes on the code blocks above.

  • The Point struct has a convenience property called IsEmpty.  This resolves to X and Y equaling 0.
  • The Point Equals overload resolved to the X and Y values.   If you have 2 instances of a Point with the same X and Y, they are equal.

Once the signature is captured on the panel, I needed a way to save the signature.  Most people capture the image.  Me, I want the signature transformed into structured data for better down-steam analysis.  Therefore, I decided to put it into XML.  To that end, I marked all of the classes in the Signature graph as Serializable.  I then created two functions to push and pull the signature out of a XML file:

private void SerializeSignature()
{
    XmlSerializer serializer = new XmlSerializer(typeof(Signature));

    if (File.Exists(fileName))
    {
        File.Delete(fileName);
    }

    using (TextWriter textWriter = new StreamWriter(fileName))
    {
        serializer.Serialize(textWriter, signature);
        textWriter.Close();
    }
}

And

private void DeserializeSignature()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(Signature));
    using (TextReader textReader = new StreamReader(fileName))
    {
        signature = (Signature)deserializer.Deserialize(textReader);
        textReader.Close();
    }
}

I then wired up the button clicks to save the signature:

private void ExportButton_Click(object sender, EventArgs e)
{
    SerializeSignature();
}

and to load it:

private void ImportButton_Click(object sender, EventArgs e)
{
    DeserializeSignature();
    ClearSignaturePanel();
    DrawSignature();

}

and these are the two other supporting methods:

private void ClearSignaturePanel()
{
    using (Graphics graphic = this.SignaturePanel.CreateGraphics())
    {
        SolidBrush solidBrush = new SolidBrush(Color.LightBlue);
        graphic.FillRectangle(solidBrush, 0, 0, SignaturePanel.Width, SignaturePanel.Height);
    }
    
}

and

private void DrawSignature()
{
    foreach (Glyph glyph in signature.Glyphs)
    {
        foreach (Line line in glyph.Lines)
        {
            DrawLine(line);
        }
    }

}

Sure enough, here is the XML in the file:

image

The problem is that this file is larger than a image file – but much more analyzable (and yes, that is a real word).  I then wanted to display the signature in a web browser.  To that end, I fired up a classic ASP.NET application and created a web control.  In the code, I rendered the points out of the XML file back into a graphic:

protected void Page_Load(object sender, EventArgs e)
{
    this.Response.ContentType = "image/gif";
    using (Bitmap bitmap = new Bitmap(200, 100))
    {
        using (Graphics graphics = Graphics.FromImage(bitmap))
        {
            SignatureFactory signatureFactory = new SignatureFactory();
            String fileName = @"C:\signature.xml";
            Signature signature = signatureFactory.LoadSignatureFromFileSystem(fileName);
            Pen pen = new Pen(Color.Red);
            foreach (Glyph glyph in signature.Glyphs)
            {
                foreach (Line line in glyph.Lines)
                {
                    graphics.DrawLine(pen, line.StartPoint.X, line.StartPoint.Y,
                        line.EndPoint.X, line.EndPoint.Y);
                }
            }

            bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
        }
    }
}

And the output on a web form:

image

Town Of Cary Information Technology Board

 

Not much sharable code this week.  I did get appointed to the Town Of Cary’s Information Technology Board:

image

RDU Code Camp Material

All of the material that I presented last Saturday at Trinug’s code camp is available here.

Removing something from a collection

Consider the following snippet:

//Remove all hexes that have a unit in them for (int i = 0; i < returnValue.Count; i++ ) { if (returnValue[i].CurrentUnit != null) { returnValue.RemoveAt(i); } } return returnValue;

This does not work.  For example, here is a screen shot:

image

The reason why is that the indexer is evaluated once,, but the list changes after each iteration.  In graphical terms:

0

1

2

3

4

5

X

X

0

1

2

3

4

X

 

 

Index 1 becomes Index 0, and since the loop is already on 1, it gets skipped for evaluation. What we need it to remove a hex and then keep looping – so the while construct needs to be used:

bool keepLooping = true; while (keepLooping == true) { int totalHexes = returnValue.Count; for (int i = 0; i < returnValue.Count; i++) { if (returnValue[i].CurrentUnit != null) returnValue.RemoveAt(i); if (totalHexes == returnValue.Count) keepLooping = false; } }

 

And the results work as expected:

image