Saturday, March 21, 2009

String Construtor String(Char[] value) doesn't work?

So for some reason that I can't determine I'm unable to use the New String(char[] value) function.  I tried this expression in my immediate window while debugging a Windows Mobile 6 .Net 3.5 application, and this is what I got:

?new string(new char[]{'1'})
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
'new string(new char[]{'1'})' threw an exception of type 'System.InvalidOperationException'
    base {System.SystemException}: {"InvalidOperationException"}

If I typed the same expression into a normal C# desktop app .Net 3.5 application, this is what I got:

?new string(new char[]{'1'})
'new string(new char[]{'1'})' threw an exception of type 'System.ArgumentException'
    base {System.SystemException}: {"Only NewString function evaluation can create a new string."}
    Message: "Only NewString function evaluation can create a new string."
    ParamName: null

I'm exteremly puzzeled.  Anyone have any ideas?

Saturday, February 7, 2009

Performing Asynchronous XML Serialization

If you work at a company anything like mine, you've had to deserialize a large XML file, and been forced to sit there for the Deserialize() method to complete. I haven't done a lot of work with threading, but I figured now was the time to start.

I decided to wrap the normal System.Xml.Serialization.XmlSerializer in a generic class that would encapsulate the threading. I also wanted it to perform some logging if there were issues during deserialization. The process starts with a factory method to return the serializer object.

        public static LoggedXMLSerializer<T> RunDeserializeAsync(string filePath) {
return new LoggedXMLSerializer<T>(filePath);
}


Which immediately calls the private constructor:

        private LoggedXMLSerializer(string filePath)
:
this() {
DeserializingDelegate = PeformDeserialization;


FileSize = new FileInfo(filePath).Length;
// The XML File tends to take up 110% of space in memory as it does on disc
FileSize = (long)(FileSize * 1.10);

TotalMemoryIncrease = 0;

Result = DeserializingDelegate.BeginInvoke(filePath, null, null);
StartingMemorySize = GetCurrentProcessMemoryInUse();
}




Which first marks the PerformDeserialization() method as the DeserializationDelegate. It then determines the file size that is being opened to be used later to determine the progress that is left. For now, it only deserializes an actual file, but it could be extended with the other default constructors of the XmlSerializer.

BeginInvoke() is called on the DeserializationDelege, which starts the deserialization and returns an IAsyncResult object. BeginInvoke() starts a new thread, and calls the assigned Delegate. You can then query the IAsyncResult object to see if it finished, or just call EndInvoke() and your primary thread will wait until the secondary thread finishes.

Immediately after the thread is created, the current size of the process is stored to also be used later to determine the progress left.

The PerformDeserialization() method is exactly what you would do if you weren't invoking it on a separate thread. Create an XmlSerialization object,assign an Event Handler for loading issues, open a file with a StreamReader and call Deserialize().

        private T PeformDeserialization(string filePath) {
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.UnknownNode += new XmlNodeEventHandler(Xs_UnknownNode);

StreamReader reader = File.OpenText(filePath);

return (T)xs.Deserialize(reader);
}


Since the Deserialize() method is still synchronous, the hardest part has been coming up with a good method of determining the progress of the file load. This is what I came up with, but if you, dear reader, have a better idea, I'd like to hear it.

        /// <summary>
/// Best guess at progress based on the size of the file, and the amount of increase in the memory of the process
/// </summary>
public int Progress {
get {
if (Result.IsCompleted) {
return 100;
}
long currentSize = GetCurrentProcessMemoryInUse();
if (currentSize < StartingMemorySize + TotalMemoryIncrease) {
// For Some reason, the current size of memory is smaller than the starting size plus the increase in memory usage
// Assume it is due to some garbage collection in between calls to Progress
// Update the starting memory size so it is equal to the current + total increase
// This assumes that no additional memory was used to deserialize the XML
StartingMemorySize = currentSize - TotalMemoryIncrease;
}
else {
TotalMemoryIncrease = currentSize - StartingMemorySize;
}

int tempProgress = (int)((currentSize - StartingMemorySize) / (double)FileSize * 100);
if (tempProgress < 0) {
tempProgress = 0;
}

if (tempProgress > 125) {
// Must have had a bad starting point, move it back to 75%
StartingMemorySize = (int)(currentSize - .75 * FileSize);
// Reinitialize Total Memory
TotalMemoryIncrease = currentSize - StartingMemorySize;
tempProgress = 75;
}

if (tempProgress > 100) {
tempProgress = 99;
}
return tempProgress;
}
}



The first thing it does, is check the IAsyncResult object to see if it has completed, if it has, then it returns 100%. Done. The next part I added later when I noticed that if I opened up more than one file, the progress of the second file would move to about 25%, then it would drop down to near 0, and stay there until it finished. I'm guessing it is due to the garbage collector collecting a large amount of memory due to the first deserialized object being release. The basic method of determining progress is then calculated, assume that the deserialized XML, will take up nearly the same amount as the serialized, is then performed. Get the increase in memory size since first beginning to deserialize the Xml, and divide it by the size of the file. Then do some checking to see if the progress has grown too large, or is over a 100%. It is not a perfect solution, but was extremely simple to implement, and serves my needs well.

Below is the entire class. Feel free to make comments.

    public class LoggedXMLSerializer<T> {
private delegate T Deserializer (string path);

private Deserializer DeserializingDelegate { get; set; }
private IAsyncResult Result { get; set; }
private long StartingMemorySize { get; set; }
private long TotalMemoryIncrease { get; set; }
private long FileSize { get; set; }
private Dictionary<string, string> XmlUnknowns {get; set;}

#region Public Properties

public T Xml { get; protected set;}

/// <summary>
/// Best guess at progress based on the size of the file, and the amount of increase in the memory of the process
/// </summary>
public int Progress {
get {
if (Result.IsCompleted) {
return 100;
}
long currentSize = GetCurrentProcessMemoryInUse();
if (currentSize < StartingMemorySize + TotalMemoryIncrease) {
// For Some reason, the current size of memory is smaller than the starting size plus the increase in memory usage
// Assume it is due to some garbage collection in between calls to Progress
// Update the starting memory size so it is equal to the current + total increase
// This assumes that no additional memory was used to deserialize the XML
StartingMemorySize = currentSize - TotalMemoryIncrease;
}
else {
TotalMemoryIncrease = currentSize - StartingMemorySize;
}

int tempProgress = (int)((currentSize - StartingMemorySize) / (double)FileSize * 100);
if (tempProgress < 0) {
tempProgress = 0;
}

if (tempProgress > 125) {
// Must have had a bad starting point, move it back to 75%
StartingMemorySize = (int)(currentSize - .75 * FileSize);
// Reinitialize Total Memory
TotalMemoryIncrease = currentSize - StartingMemorySize;
tempProgress = 75;
}

if (tempProgress > 100) {
tempProgress = 99;
}
return tempProgress;
}
}

/// <summary>
/// Returns true when the XML has finished being Deserialized
/// Returns false if it hasn't
/// </summary>
public bool IsCompleted {
get {
if (Result.IsCompleted) {
Xml = DeserializingDelegate.EndInvoke(Result);
return true;
}
else {
return false;
}
}
}

#endregion // Public Properties

/// <summary>
/// Returns a list of all unknown nodes found in the XML in this format
/// Entity Name, First Occurance Line Number, First Occurance Line Position
/// </summary>
/// <returns></returns>
public string GetLog() {
StringBuilder sb = new StringBuilder();
foreach (var item in XmlUnknowns) {
sb.Append(item.Key + ", " + item.Value + Environment.NewLine);
}
return sb.ToString();
}


private LoggedXMLSerializer()
:
base() { // Force Factory Method Use
XmlUnknowns = new Dictionary<string, string>();
}

private LoggedXMLSerializer(string filePath)
:
this() {
DeserializingDelegate = PeformDeserialization;


FileSize = new FileInfo(filePath).Length;
// The XML File tends to take up 110% of space in memory as it does on disc
FileSize = (long)(FileSize * 1.10);

TotalMemoryIncrease = 0;

Result = DeserializingDelegate.BeginInvoke(filePath, null, null);
StartingMemorySize = GetCurrentProcessMemoryInUse();
}

/// <summary>
/// Deserializes the XML on a different thread. Use IsCompleted and Progress to determine status
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static LoggedXMLSerializer<T> RunDeserializeAsync(string filePath) {
return new LoggedXMLSerializer<T>(filePath);
}

private T PeformDeserialization(string filePath) {
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.UnknownNode += new XmlNodeEventHandler(Xs_UnknownNode);

StreamReader reader = File.OpenText(filePath);

return (T)xs.Deserialize(reader);
}

private long GetCurrentProcessMemoryInUse() {
Process process = Process.GetCurrentProcess();
return process.WorkingSet64;
}

private void Xs_UnknownNode(object sender, XmlNodeEventArgs e) {
if (!XmlUnknowns.ContainsKey(e.Name)) {
XmlUnknowns.Add(e.Name, e.LineNumber + ", " + e.LinePosition);
}
}
}

Easing Constraints Without Duplicating Queries

I had a rather common problem at work that I created a rather elegent solution for.  Lets say for instance you had a database table that contained a list of businesses, the city they operated in, the state they operated in, and their FEIN.  You were given a list of business names, and asked to find the correct FEIN for each business. You need to search for the business by name, city, and state first. If you don't find it, then search for the business by name and city. If you still don't find it, you finally just need to search by the name, returning the first record each time if there are duplicates. You've used LINQ to SQL to get a collection of the data, and now you need to return the best match.  At first you may do what I did at first, something like this:

var feins1 = from business in Database
where business.Name == name
&& (business.City == city)
&& (
business.State == state)
select business.FEIN;

if (feins1.Count() > 0) {
return feins1.First();
}

var feins2 = from business in Database
where business.Name == name
&& (business.City == city)
select business.FEIN;

if (feins2.Count() > 0) {
return feins2.First();
}

var feins3 = from business in Database
where business.Name == name
select business.FEIN;

if (feins3.Count() > 0) {
return feins3.First();
}


You reach for the ctrl-c and ctrl-v on your keyboard, and suddenly feel really dirty. What if another criteria needs to be added? You'll have to add another criteria to each where statement, as well as adding an entirely new query. I spent a few minutes thinking about it, and came up with this solution:

    for (int i = 0; i < 3; i++) {
fein = GetBestFEIN("Good Times Inc", "Indianapolis", "IN", i > 1, i > 0);

if (fein != string.Empty) {
break;
}
}
return fein;
}

private string GetBestFEIN(string name, string city, string state, bool skipCity, bool skipState) {

var Database = from i in new string[] { "0", "1", "2", "3" }
select new { Name = i, FEIN = i, City = i, State = i };

var feins = from business in Database
where business.Name == name
&& (
skipCity || business.City == city)
&& (
skipState || business.State == state)
select business.FEIN;

if (feins.Count() == 0) {
return string.Empty;
}
else {
return feins.First();
}
}





Now if another criteria is added, you just need to increase the for each loop by one, and add another parameter. I made my change, and went home feeling a lot cleaner.

Thursday, November 27, 2008

Web Stripper

For my Scramble Cheater program, I needed to get a list of all possible words for a dictionary. I found a good website call Word Snipe, that listed all the words from the game, and orderd them by word length. This resulted in 105,000 words, spread out 50 at a time, on over 2000 pages. I didn't want to have to copy and past all these words by hand, so I created this program to strip them from the website. It took about 35 minutes for it to download all the words, but it was definetly a lot easier than doing it by hand.

Below is the code. Enjoy!


    public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
int value = 1;
while (value <= 105351) {
ParseResponse(GetResponse("http://wordsnipe.com/results.php?start=" + value + "&PHPSESSID=1af1f78a57145ebc9c14fd4441fcf077"));
value += 50;

}
}

private void ParseResponse(string htmlResponse) {
int index = 0, endIndex;
string startDiv = "<div class=\"result\">";
int startDivLength = startDiv.Length;

for (int i = 0; i < 50; i++) {
index = htmlResponse.IndexOf(startDiv, index);
index = htmlResponse.IndexOf(">", index + startDivLength) + 1;
endIndex = htmlResponse.IndexOf("</a>", index);
textBox1.AppendText(string.Format("AllWords.Add(\"{0}\");{1}", htmlResponse.Substring(index, endIndex - index), Environment.NewLine));
index = endIndex;
}
}

private string GetResponse(string urlAddress) {
Uri uri = new Uri(urlAddress);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "GET";
string result = string.Empty;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
using (Stream responseStream = response.GetResponseStream()) {
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)) {
result = readStream.ReadToEnd();
}
}
}
return result;
}
}



Beating Scramble On FaceBook




I was playing this Scramble game for Facebook over The Thanksgiving Holiday, and decided that I wanted to write a program to cheat at the game, and get high scores that would blow my friends out of the water. So did. I was able to score 1553 points, which is about 1400 points more than my nearest friend on Facebook. So much fun.
The Source Code and a more indepth description is on CodeProject. http://www.codeproject.com/KB/cs/WordScramble.aspx

Friday, October 31, 2008

Automated CSLA Testing Helper

I was trying to come up with my first test project using the Tester built into VS 2008. I wanted to be able to do some basic CRUD testing on my Csla Business Objects.  I quickly realized that I didn't want to have to go through and set all of my properties by hand for every single class.  Even if I had all the time in the world to do that, if they changed the database schema, which would result in me having to re-code-gen the BOs, I would have to edit my test scripts to handle any new columns (which I would always forget) and remove any columns that no longer exist.  What a pain.

Enter Reflection.  I was able to create a generic SetPropertyValues function that loops through all the properties of any BusinessObject and automatically assigns all them all a different value.  
This is how it works:
    1. Using reflection, I loop through all the properties on the BO with a counter that is incremented each time
    2. I look at the type of the property and assign it a value based off of its type, using the counter as a base
    3. I then save the value off to a generic list of PropertyInfo, and string values to compare with later.
Thats it.

I then wraped that funciton with two other functions, one to perform the intial insert, and one with a different seed value, to perform an update test.  Below is the .Net test class I setup for my customer class, and the SetPropertyValues function that is used to simplify the test.

Enjoy.




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BusinessObjectsUnitTest {
static class G2TestHelper {

public static List<PropertyCallerValuePair> SetInitialPropertyValues<T>(Csla.BusinessBase<T> target) where T : Csla.BusinessBase<T> {
return SetPropertyValues(target, 0);
}

public static List<PropertyCallerValuePair> SetUpdatedPropertyValues<T>(Csla.BusinessBase<T> target) where T : Csla.BusinessBase<T> {
return SetPropertyValues(target, 1);
}

private static List<PropertyCallerValuePair> SetPropertyValues<T>(Csla.BusinessBase<T> target, int intialValue) where T : Csla.BusinessBase<T> {
List<PropertyCallerValuePair> values = new List<PropertyCallerValuePair>();
string stringValue = string.Empty;

foreach (PropertyInfo property in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(p => p.CanWrite && !(p.PropertyType is Csla.Core.IBusinessObject))) {

if(typeof(string).IsAssignableFrom(property.PropertyType)){
stringValue = intialValue.ToString();
property.SetValue(target, stringValue, null);
}
else if (typeof(bool).IsAssignableFrom(property.PropertyType)) {
}
else if (typeof(long).IsAssignableFrom(property.PropertyType) ||
typeof(int).IsAssignableFrom(property.PropertyType) ||
typeof(decimal).IsAssignableFrom(property.PropertyType)) {
stringValue = intialValue.ToString();
property.SetValue(target, intialValue, null);
}
else if (typeof(Csla.SmartDate).IsAssignableFrom(property.PropertyType)) {
Csla.SmartDate time = new Csla.SmartDate(DateTime.Now.AddDays(intialValue));
stringValue = time.ToString();
property.SetValue(target, time, null);
}
else if (typeof(DateTime).IsAssignableFrom(property.PropertyType)){
DateTime time = DateTime.Now.AddDays(intialValue);
stringValue = time.ToString();
property.SetValue(target, stringValue, null);
}
else {
throw new Exception("Unrecognized Type");
}

values.Add(new PropertyCallerValuePair(property, stringValue));
intialValue++;
}

return values;
}

public static void AssertAreEqual<T>(Csla.BusinessBase<T> target, List<PropertyCallerValuePair> values) where T : Csla.BusinessBase<T> {
foreach (PropertyCallerValuePair property in values) {
Assert.AreEqual(property.Value, property.Property.GetValue(target, null).ToString());
}
}
}

public class PropertyCallerValuePair
public PropertyInfo Property { get; set; }
public string Value { get; set; }

public PropertyCallerValuePair(PropertyInfo property, string value) {
Property = property;
Value = value;
}
}
}






Hear is the extremely simple test script would could easily be code generated:
        /// <summary>
///A test for Customer CRUD
///</summary>
[TestMethod()]
public void CustomerCRUD() {
//Begin Create
Customer expected = Customer.NewCustomer();
List<PropertyCallerValuePair> values = G2TestHelper.SetInitialPropertyValues(expected);
Customer actual = expected.Save();
//Test Create
G2TestHelper.AssertAreEqual(actual, values);
//End Create

expected = actual;

//Begin Read
actual = Customer.GetCustomer(expected.CustId);
//Test Read
G2TestHelper.AssertAreEqual(actual, values);
//End Read

expected = actual;

//Begin Update
values = G2TestHelper.SetUpdatedPropertyValues(expected);
expected = expected.Save();
G2TestHelper.AssertAreEqual(expected, values);
actual = Customer.GetCustomer(expected.CustId);
//Test Update
G2TestHelper.AssertAreEqual(actual, values);
//End Update

expected = actual;

//Begin Delete
Customer.DeleteCustomer(expected.CustId);
try {
actual = Customer.GetCustomer(expected.CustId);
}
catch {
actual = null;
}
//Test Delete
Assert.IsNull(actual);
//End Delete
}


Friday, October 17, 2008

Updating A Private Automatic Property

I had an issue at work today where I was trying to update a public get, private set automatic propety using reflection.

My first issue was I didn't now that when you reflect a type, you can access all the inherited public scoped methods and properties and fields, but you can't access any inherited private methods, properties, and fields. Once I had that figured out, I just had to figure out what the name of the field was.

I downloaded Red Gate's .Net Reflector (an awesome tool) and dissambled my sample test program. I then looked at the property generated by the compiler,

// Fields
[CompilerGenerated]
private long <CustId>k__BackingField;

// Properties
public long CustId

[
CompilerGenerated]
get
{
return this.<CustId>k__BackingField;
}
private [CompilerGenerated]
set
{
this.<CustId>k__BackingField = value;
}






And as you can quickly see, the name of the backing field for an automatic property is as follows, k__BackingField. Once I had the backing name figured out, I could update just like any other nonpublic field:

WinPart parent = new WinPart(_mainForm);
parent.GetType().GetField("<CustId>k__BackingField", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(this, newCustId);