Using AutoMapper for MVVM implementations

Being Clean Code Developers, whenever we start developing a new application, we try to improve our code quality, right? As a part of that, we librarify what can be librarified and use 3rd Party and Open Source assemblies wherever possible so we can concentrate on the really dirty work.

OK, here's one thing Stefan Lieser brought to my attention in the course a Google Group discussion. It's called AutoMapper, and as the name gives away is a great deal of help when you have to map instances of Type A to instances of type B (very simply put, really). Sounds rather boring at first glance, but me and my buddy Maik decided we'd take a look at it for our nhibernate based MVVM implementations, in which (up to now) the viewmodels were wrappers / proxies for the models. Apart from that, it does great Conversions from one list type to another, which was a numb piece of loop-through-source-store-in-destination.

The Gloria : Stickiness of memory addresses
Having worked with NHibernate, you will have passed the point where you had to think about change tracking, a topic that will end up in overridden equality operators, which others have written about.
What turns out to be important in the whole process is the consistency of an object's memory address. Our wrapper ViewModels had to keep an inner Model instance and write through all changes made to its values to the inner object. This was prone to errors (copy & paste, forgetfulness, over-tired because of long gaming nights) and burdensome, but necessary in order to keep the original model's address.
Using Automapper allows to switch the class Type (to 'n' fro!) without loosing the memory location at any time, so it's a neat util for getting a ViewModel for a Model. Let the code speak.


public class Customer
{
public int Id { get; set; }

public string Name { get; set; }

public override string ToString()
{
return "CustomerModel: " + this.Id + " - " + this.Name;
}
}


public class CustomerView
{
public int Id { get; set; }

public string Name { get; set; }

public override string ToString()
{
return "CustomerViewModel: " + this.Id + " - " + this.Name;
}
}


Now let's prove how the memory address remains unchanged. For that I have put together a small console-application.


static void Main(string[] args)
{
//creating a convertee
var customer = new Customer()
{
Id = 1,
Name = "me"
};

//Creating Maps for 2-way mapping
Mapper.CreateMap<Customer, CustomerView>();
Mapper.CreateMap<CustomerView, Customer>>();

// First mapping Model-->ViewModel
CustomerView view = Mapper.Map<Customer, CustomerView>(customer);
Console.WriteLine(customer + ", mem addr = " + WriteMemAddr(customer));
Console.WriteLine(view + ", mem addr = " + WriteMemAddr(view));

// Now, change the ViewModel and Re-Convert it.
view.Name = "you";
var customer2 = Mapper.Map<CustomerView, Customer>(view);
Console.WriteLine(customer2 + ", mem addr = " + WriteMemAddr(customer2));
Console.ReadLine();
}


static string WriteMemAddr(object o)
{
GCHandle handle = GCHandle.Alloc(o, GCHandleType.Normal);
IntPtr pointer = GCHandle.ToIntPtr(handle);
string pointerDisplay = pointer.ToString();
handle.Free();
return pointerDisplay ;
}


Now run this. You will see that while converting the object is always in the same memory location. If that ain't gorgeous!

Another sample/explanation can be found here .

Cheers!

Kommentare

Beliebte Posts aus diesem Blog

Deploying ClickOnce-applications in different environments without modifying the assembly identity

Preparing for and passing MCTS exam 70-536