Frameworks

Question about AutoMapper Performance

February 28, 2010 .NET, AutoMapper, Frameworks 4 comments

If you haven’t read my previous article on AutoMapper, please read it first.

After I’ve posted this article one guy was really concerned about the performance of AutoMapper.
So, I have decided to measure execution time of the AutoMapper mapping and manual mapping code.

First of all I have code which returns me 100000 almost random Customers which goes to the customers list.

Measurement of AutoMapper mapping time:

            stopwatch.Start();
            var autoMapperCVI = new List<CustomerViewItem>();
            foreach (var customer in customers)
            {
               autoMapperCVI.Add(Mapper.Map<Customer,CustomerViewItem>(customer));
            }
            stopwatch.Stop();
            Console.WriteLine(string.Format(“AutoMapper: {0}”, stopwatch.ElapsedMilliseconds));

Measurement of the manual mapping time:

            stopwatch.Start();
            var manualCVI = new List<CustomerViewItem>();
            foreach (var customer in customers)
            {
                var customerViewItem = new CustomerViewItem()
                                           {
                                               FirstName = customer.FirstName,
                                               LastName = customer.LastName,
                                               FullName = customer.LastName + ” “ + customer.FirstName,
                                               DateOfBirth = customer.DateOfBirth.ToLongDateString(),
                                               CompanyName = customer.Company.Name,
                                               NumberOfOrders = customer.NumberOfOrders,
                                               VIP = customer.VIP ? “Y” : “N”
                                           };
                manualCVI.Add(customerViewItem);
            }
            stopwatch.Stop();           
            Console.WriteLine(string.Format(“Manual Mapping: {0}”, stopwatch.ElapsedMilliseconds));

I ran my tests many times and one of the possible outputs could be:

AutoMapper: 2117
Manual Mapping: 293

It looks like manual mapping is 7 times faster than automatical. But hey, it took 2 sec to map handrend thouthands of customers.

It is one of the situations where you should decide if the performance is so critical for you or no. I don’t think that there are a lot of cases when you really need to choice manual mapping exactly because of performance issue.


4 comments


AutoMapper

February 25, 2010 .NET, AutoMapper, Frameworks 4 comments

The Problem

Have you ever faced need to write code, which looks like here:

            Customer customer = GetCustomerFromDB();

            CustomerViewItem customerViewItem = new CustomerViewItem()
                                       {
                                           FirstName = customer.FirstName,
                                           LastName = customer.LastName,
                                           DateOfBirth = customer.DateOfBirth,
                                           NumberOfOrders = customer.NumberOfOrders
                                       };

            ShowCustomerInDataGrid(customerViewItem);

Our scenario could be like:
We have our domain model which has Customer entity and we are going to show Customers in DataGrid, and for that we need much lighter object CustomerViewItem, list of which is bounded to the Grid.

As you see there are four lines of code which are just copying values from one object to another. Could also be that you will need to show up to 10-15 columns in you grid. What then?

Would you like to have something that will do mapping from Customer to the CustomerViewItem automatically?

Of course you do, especially if you have another situation like mapping of heavy data objects into DTO objects which are considered to be send though the wire.

AutoMapper

From the AutoMapper codeplex web page we see that “AutoMapper is an object-object mapper. Object-object mapping works by transforming an input object of one type into an output object of a different type. What makes AutoMapper interesting is that it provides some interesting conventions to take the dirty work out of figuring out how to map type A to type B. As long as type B follows AutoMapper’s established convention, almost zero configuration is needed to map two types.“, so in other words it provides the solution for our problem.

To get started go and download it here. It is standalone assembly, so you should not get difficulties with including reference to it in your project.

So in order to ask AutoMapper do dirty work instead of me, we need to add next line somewhere in the start of our code execution:

            Mapper.CreateMap<Customer, CustomerViewItem>();

Once we have that we are done and we can use pretty nice code to get our mapped object:

            Customer customer = GetCustomerFromDB();

            CustomerViewItem customerViewItem = Mapper.Map<Customer, CustomerViewItem>(customer);

            ShowCustomerInDataGrid(customerViewItem);

Lets take a look on whole code base to see all about what I’m going to talk further:

    class Program
    {
        static void Main(string[] args)
        {
            var program = new Program();
            Mapper.CreateMap<Customer, CustomerViewItem>();
            program.Run();
        }

        private void Run()
        {
            Customer customer = GetCustomerFromDB();

            CustomerViewItem customerViewItem = Mapper.Map<Customer, CustomerViewItem>(customer);

            ShowCustomerInDataGrid(customerViewItem);
        }

        private void ShowCustomerInDataGrid(CustomerViewItem customerViewItem){}

        private Customer GetCustomerFromDB()
        {
            return new Customer()
            {
                DateOfBirth = new DateTime(1987, 11, 2),
                FirstName = “Andriy”,
                LastName = “Buday”,
                NumberOfOrders = 7
            };
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }

        public int NumberOfOrders { get; set; }
    }

    public class CustomerViewItem
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }

        public int NumberOfOrders { get; set; }
    }


   
And proving that all values has been mapped take a look on the picture:

More Complex Example 1 (Custom Map)

So far we know all to have extremely simple mapping. But what if we need something more complex, for example, CustomerViewItem should have FullName, which consists with First and Last names of Customer?

After I just added public string FullName { get; set; } to the CustomerViewItem and run my application in debug I got null value in that property. That is fine and is because AutoMapper doesn’t see any FullName property in Customer class. In order to “open eyes” all you need is just to change a bit our CreateMap process:

            Mapper.CreateMap<Customer, CustomerViewItem>()
                .ForMember(cv => cv.FullName, m => m.MapFrom(s => s.FirstName + ” “ + s.LastName))


And results are immediately:

More Complex Example 2 (Flattening)

What if you have property Company of type Company:

    public class Customer
    {
        public Company Company { get; set; }
        //…
    }

    public class Company
    {
        public string Name { get; set; }
    }


and want to map it into CompanyName of the view class

    public class CustomerViewItem
    {
        public string CompanyName { get; set; }
        //…
    }


How do you think what do you need to change in your mapping to make this work?

Answer: NOTHING. AutoMapper goes in deep of your classes and if names matches it will do mapping for you.

More Complex Example 3 (Custom type resolvers)

What if you have boolean property VIP in your Customer class:

    public class Customer
    {
        public bool VIP { get; set; }
    }


and want to map it into string VIP and represent like “Y” or “N” instead

    public class CustomerViewItem
    {
        public string VIP { get; set; }
    }

   
Well, we can solve this the same way we did for the FullName, but more appropriate way is to use custom resolvers.
So lets create customer resolver which will resolve VIP issue for us.

It looks like:

    public class VIPResolver : ValueResolver<bool , string >
    {
        protected override string ResolveCore(bool source)
        {
            return source ? “Y” : “N”;
        }
    }


And only one line is needed for our CreateMap process:

    .ForMember(cv => cv.VIP, m => m.ResolveUsing<VIPResolver>().FromMember(x => x.VIP));

More Complex Example 4 (Custom Formatters)

What if I want AutoMapper to use my custom formatting of the DateTime instead of just using ToString, when it does mapping from DateTime to String property?
Let say I want use ToLongDateString method to show birth date with fashion.

For that we add:

    public class DateFormatter:IValueFormatter
    {
        public string FormatValue(ResolutionContext context)
        {
            return ((DateTime) context.SourceValue).ToLongDateString();
        }
    }


And making sure that AutoMapper knows where to use it:

                .ForMember(cv => cv.DateOfBirth, m => m.AddFormatter<DateFormatter>());
So, now I’ve got:

Great, isn’t it? BirthDate is even in my native language.

I hope my article was interesting to read and it gave you ideas how you can utilize this new feature called “AutoMapper”.


4 comments


Managed Extensibility Framework

January 27, 2010 .NET, Frameworks, MEF 4 comments

MEF is the Framework which allows you to load extensions to you application easily. It does discovery and composition of parts you need to be included in your application at run-time. You could extend your behavior simply with adding new Plugin. Managed Extensibility Framework will do everything for you.

Hello MEF World!

Assume we have really simple application and we want it to say “Hello MEF World!“:

    class Program
    {
        static void Main(string[] args)
        {
            var program = new Program();
            program.Run();
        }
        private void Run()
        {
            ProgrammGreeter.SayHello();
        }
        protected IGreeter ProgrammGreeter{ get; set;}
    }
    public interface IGreeter
    {
        void SayHello();
    }
    public class Greeter:IGreeter
    {
        public void SayHello()
        {
            Console.WriteLine(“Hello MEF World!”);
        }
    }

That is absolutely how this look and we want to make this work. The main issue is to have instance in property ProgrammGreeter to be real instance of Greeter.

Lets accomplish this with MEF

In order to do this we need to include reference to System.ComponentModel.Composition.

Accordingly to MSDN: “MEF is an integral part of the .NET Framework 4 Beta 1, and is available wherever the .NET Framework is used. You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET. In addition, there are plans to add MEF support for Silverlight applications.

Most likely MEF will be included into .NET Framework 4.0, but for now we could download it from codeplex site here.

Once we added reference we could add Import and Export attributes.
Export stands for exposing some capabilities and Import stands for dependency on some other capability.

Our Greeter provides some capabilities so we add Export there:

    [Export(typeof(IGreeter))]
    public class Greeter : IGreeter

We want to use that capability in our Programm class, we depend on that functionality. Add Import:

        [Import]
        protected IGreeter ProgrammGreeter { get; set; }

Usually our capabilities lives in other asseblies, but also they could live in called assembly. Anyway we need to say how to compose all our dependencies to MEF.
This could be done with method Compose which we be calling before we are using capabilities, usually at the start of app:

        private void Run()
        {
            Compose();
            ProgrammGreeter.SayHello();
        }
        private void Compose()
        {
            var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var compositionContainer = new CompositionContainer(assemblyCatalog);
            compositionContainer.ComposeParts(this);
        }

I ran my application and got:

How does Managed Extensibility Framework work?

I think that you are bit concerned/confused regarding that Compose method. Just read comments in code of Compose, which I made more detailed:

        //We need guide MEF how to Compose all we need
        private void Compose()
        {
            //Catalog says where to search for capabilities (Where do exports live)
            var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            //CompositionContainer holds defined dependencies and coordinates creation
            var compositionContainer = new CompositionContainer(assemblyCatalog);
            //CompositionBatch object holds references to all objects that need to be composed
            var compositionBatch = new CompositionBatch();
            //one of such objects is Programm instance (this), it needs to be composed
            compositionBatch.AddPart(this);
            //And finally Container has method called Compose to do actuall Composing
            compositionContainer.Compose(compositionBatch);
        }

In Managed Extensibility Framework there are primitives called ComposablePart which holds extensions to your application grabbed from Catalog. But also it might be that they have Imports which also needed to be composed.

Take a look on this picture from Managed Extensibility Framework wiki page.

More complex Example

In this example we will have application which parses XML file (contains information about some developer). Then when we want to deploy our application to Clients we want that XML to pass some rules, but they could differ from Client to Client. To accomplish this we put rules into separate dll and will work with it as with plugin.

We have two assemblies:

  • MEF.DEMO which declares ISecurityRule and IDataRule.
  • MEF.Rules has implementation of those interfaces.

Like on picture below. I simply don’t want to bore you with explaining of Rules logic. If you want sources just ping me.

Our Programm class wants to load rules from other assembly so we put Imports.

        [Import]
        public ISecurityRule SecurityRule { get; set; }
        [ImportMany]
        public IDataRule[] DataRules { get; set; }
        public void Run()
        {
            Console.WriteLine(“Programm run.”);
            Compose();
            Console.WriteLine(“Composition completed.”);
            var document = XDocument.Load(“developer.xml”);
            Console.WriteLine(document.ToString());
            var passesValidation = SecurityRule.PassesValidation(document);
            Console.WriteLine(string.Format(“Rule {0}: {1}”, SecurityRule.GetType(), passesValidation));
            foreach (var d in DataRules)
            {
                var valid = d.IsValid(document);
                Console.WriteLine(string.Format(“Rule {0}: {1}”, d.GetType(), valid));
            }          
        }

As you noticed we are using ImportMany, name says for itself.

We need to change our Compose method to search for Exports in Directory where execution assembly is located. For that we use DirectoryCatalog.

        private void Compose()
        {
            var catalog = new DirectoryCatalog(Environment.CurrentDirectory);
            var container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }

Put those dlls in one folder, and run MEF.DEMO. You will get:

The goal of MEF is to seamlessly glue together classes which import services from other parts of the application, and some classes which export those services. You could say that MEF is like DI container. Yes it has a lot of it, but Managed Extensibility Framework is concentrated on composition. And that composition could be done at run time at any point of time you want that to happen. Also you could do re-composition whenever you want to do that. You could load capabilities with Lazy technical or add some metadata to your exports. Discovering of dependencies in Catalog could be done with Filtering.

Managed Extensibility Framework is great feature, that Microsoft added to .NET 4.0 Framework.


4 comments