Friday, August 14, 2009

GetHashCode using MD5

Wanted to have a way to get a hash code for an object, and the code will be different when the data within the object changes. Only supported for objects that support serialization... but it is better then nothing...


public static class HashCodeGenerator
{
public static string GetMD5HashCode(this object obj)
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Flush();
var data = stream.ToArray();
StringBuilder sBuilder = new StringBuilder();

// get the hash code of the object.
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hashBytesArray = md5.ComputeHash(data);

// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < hashBytesArray.Length; i++)
{
sBuilder.Append(hashBytesArray[i].ToString("x2"));
}

return sBuilder.ToString();
}

public static bool CompareMD5HashCode(this object obj, string hashCode)
{
string hash = obj.GetMD5HashCode();
bool isMatch = false;
if (hash == hashCode)
isMatch = true;

return isMatch;
}
}

Thursday, August 13, 2009

Object to XML and XML to Object

I always need this code... so now its on my page!


internal static class XmlSerializerHelper
{
public static object GetObjectFromXml(string xml, Type type)
{
XmlSerializer ser = new XmlSerializer(type);
object value = ser.Deserialize(new StringReader(xml));
return value;
}

public static string GetXmlFromObj(object obj, Type type)
{
string xml;
XmlSerializer ser = new XmlSerializer(type);
using (StringWriter writer = new StringWriter())
{
ser.Serialize(writer, obj);
writer.Flush();
xml = writer.ToString();
}

return xml;
}

public static string ToXml(this object obj)
{
Type type = obj.GetType();
string xml = GetXmlFromObj(obj, type);
return xml;
}

}

DataForm Control supporting nested classes


One of the cool things in the toolkit is a new DataForm control. You can give it any object and it will produce a form that will allow you to edit / read your object. However, I noticed that the DataForm, out of the box does not support "auto generation" of fields for nested complex types. This is something that sounds simple to support out of the box, becasue a nested class is really another DataForm control nested within its parent DataForm. Still, when tyring to put a complex type, the Dataform control simply puts a textbox and put the ToString() value of your complex type as its value. Not very useful.

With the help of the UI guy at my work, we found a way to change this limitation and allow for nested UI. I will include the code in this post, but it is mostly testing code and prototype code. You can take it and modify it for your needs.

To do this we creaed a SuperDataForm control



using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Collections.Generic;

namespace ParameterManagement
{
public class SuperDataForm : DataForm
{
List Controls = new List();

public bool CompositeItemIsValid;
public SuperDataForm()
{
this.Loaded += new RoutedEventHandler(SuperDataForm_Loaded);

}

void SuperDataForm_Loaded(object sender, RoutedEventArgs e)
{
if (this.CurrentItem == null)
{
this.CurrentItem = this.DataContext;
}
}

protected override void OnAutoGeneratingField(DataFormAutoGeneratingFieldEventArgs e)
{
// normally change this condition to check it is one of your complex types
// or that it is not a basic type.
if (e.PropertyType == typeof(NestedComplexType))
{
var control = new SuperDataForm();

control.CommandButtonsVisibility = DataFormCommandButtonsVisibility.All;
control.IsReadOnly = false;
Controls.Add(control);
Binding binding = new Binding(e.PropertyName);
binding.Mode = BindingMode.TwoWay;
binding.ValidatesOnExceptions = true;
binding.NotifyOnValidationError = true;
control.SetBinding(DataForm.CurrentItemProperty, binding);
e.Field.IsReadOnly = false;
e.Field.Content = control;
}

}

protected override void OnValidatingItem(System.ComponentModel.CancelEventArgs e)
{
// this is needed to have validation on the children controls
foreach (var control in Controls)
{
if (!control.ValidateItem())
{
CompositeItemIsValid = false;
break;
}
}
}

protected override void OnCurrentItemChanged(EventArgs e)
{

}



}
}


Download Code Here