2

I want to somehow map entity object to business object using reflection in c# -

public class Category
    {
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
    }

My Entity Class has same properties, CategoryId and CategoryName.Any best practice using reflection or dynamic would be appreciated.

Vishal
  • 11,819
  • 16
  • 79
  • 125
Hidsman
  • 119
  • 1
  • 4
  • 12

3 Answers3

16

You can use Automapper or Valueinjecter

Edit:

Ok I wrote a function that uses reflection, beware it is not gonna handle cases where mapped properties aren't exactly equal e.g IList won't map with List

public static void MapObjects(object source, object destination)
{
    Type sourcetype = source.GetType();
    Type destinationtype = destination.GetType();

    var sourceProperties = sourcetype.GetProperties();
    var destionationProperties = destinationtype.GetProperties();

    var commonproperties = from sp in sourceProperties
                           join dp in destionationProperties on new {sp.Name, sp.PropertyType} equals
                               new {dp.Name, dp.PropertyType}
                           select new {sp, dp};

    foreach (var match in commonproperties)
    {
        match.dp.SetValue(destination, match.sp.GetValue(source, null), null);                   
    }            
}
Serguzest
  • 1,277
  • 10
  • 18
  • i dont want to use any third party or open source – Hidsman Mar 08 '11 at 17:22
  • string destinationPropertyName = LookupMapping(sourceType.ToString(),destinationType.ToString(),sourceProperty.Name ) ; Here LookupMapping is Microsoft Dynamic CRM Function. how i can do it without CRM – Hidsman Mar 08 '11 at 18:15
  • i need to use reflection to avoid fix number of properties. – Hidsman Mar 08 '11 at 21:46
  • I wonder what makes you think it doesn't use reflection? GetValue, SetValue those are reflection methods. – Serguzest Mar 09 '11 at 10:58
  • @Aaabb Bbaa with Valueinjecter you would do a.InjectFrom(b) and that's it – Omu Mar 09 '11 at 21:17
  • 1
    I recently started working on a new project and found a copied version of this code in it. I would strongly recommend using AutoMapper or ValueInjecter as @Serguzest initially suggested as this piece of code created problems in our applications. For example, a List would be null in the destination. – Michael Feb 22 '12 at 18:16
  • Tried your solution (in VB.NET but it's the same). I've added "If match.dp.CanWrite Then" in the foreach cycle. Destination property could not have a setter. I also changed the method signature in this way to make the method more typed: "Public Shared Sub MapObjects(Of T, S)(source As T, destination As S)". Hope it helps. – GiveEmTheBoot Jul 08 '14 at 12:14
0

This is something that I wrote to do what I think you are trying to do and you don't have to cast your business objects:

public static TEntity ConvertObjectToEntity<TEntity>(object objectToConvert, TEntity entity) where TEntity : class
    {
        if (objectToConvert == null || entity == null)
        {
            return null;
        }

        Type BusinessObjectType = entity.GetType();
        PropertyInfo[] BusinessPropList = BusinessObjectType.GetProperties();

        Type EntityObjectType = objectToConvert.GetType();
        PropertyInfo[] EntityPropList = EntityObjectType.GetProperties();

        foreach (PropertyInfo businessPropInfo in BusinessPropList)
        {
            foreach (PropertyInfo entityPropInfo in EntityPropList)
            {
                if (entityPropInfo.Name == businessPropInfo.Name && !entityPropInfo.GetGetMethod().IsVirtual && !businessPropInfo.GetGetMethod().IsVirtual)
                {
                    businessPropInfo.SetValue(entity, entityPropInfo.GetValue(objectToConvert, null), null);
                    break;
                }
            }
        }

        return entity;
    }

Usage example:

public static Category GetCategory(int id)
    {
        return ConvertObjectToEntity(Database.GetCategoryEntity(id), new Category());
    }
Gaff
  • 5,182
  • 3
  • 36
  • 49
0

http://automapper.codeplex.com/

My vote is for auto mapper. I currently use this. I've done performance tests on it, and although it is not as fast as hand mapping (below):

Category c = new Category 
  {
    id = entity.id,
    name = entity.name
  };

The trade off for mapping automatically makes it an obvious choice, at least for the entity to business layer mapping. I actually hand map from the business layer to the view model because I need the flexibility.

Ladislav Mrnka
  • 355,666
  • 57
  • 651
  • 662