Created
February 17, 2012 13:45
-
-
Save dervalp/1853521 to your computer and use it in GitHub Desktop.
Mapper C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [AttributeUsage(AttributeTargets.Property)] | |
| public sealed class NotMappingAttribute : Attribute | |
| { | |
| public bool Value { get; private set; } | |
| public NotMappingAttribute() | |
| { | |
| Value = true; | |
| } | |
| } | |
| public class Mapper<TSource, TDestination> | |
| { | |
| /// <summary> | |
| /// Dictionnary Used for supporting Aggregates | |
| /// Dictionnary { | |
| /// Model.Address : AddressViewModel | |
| /// Model.WhatEvertComesFromDomain : WhateverViewModel | |
| /// } | |
| /// </summary> | |
| Dictionary<string, string> MappingRelations { get; set; } | |
| /// <summary> | |
| /// Constructor, pass Aggregates relation for supporting them | |
| /// </summary> | |
| /// <param name="mappingInformationDomainToViewModel"></param> | |
| public Mapper(Dictionary<string, string> mappingInformationDomainToViewModel = null) | |
| { | |
| MappingRelations = mappingInformationDomainToViewModel; | |
| } | |
| /// <summary> | |
| /// Take instance of sourceType and map an instance of destinationType | |
| /// If no MappingRelations defined during CTOR: | |
| /// map ONLY PROPERTIES with the SAME NAME and SAME TYPE | |
| /// If MappingRelations defined during CTOR: | |
| /// Reccursivelly instanciate the MapClass<TSource, TDestination> and called the MapClassReflection with types passed | |
| /// For example : MapClassReflection<AddressViewModel,AddressViewModel> is instanciate and the MapClassReflection method | |
| /// is called | |
| /// </summary> | |
| /// <param name="source">Source Type</param> | |
| /// <param name="destination">Destination Type</param> | |
| public void MapClassReflection(TSource source, TDestination destination) | |
| { | |
| if (source != null) | |
| { | |
| try | |
| { | |
| foreach (PropertyInfo sourceProperty in source.GetType().GetProperties()) | |
| { | |
| string destinationPropertyName = LookupForPropertyInDestinationType(sourceProperty.Name, destination.GetType()); | |
| if (destinationPropertyName != null) | |
| { | |
| PropertyInfo destinationProperty = destination.GetType().GetProperty(destinationPropertyName); | |
| NotMappingAttribute DoNotMap = (NotMappingAttribute)Attribute.GetCustomAttribute(destinationProperty, typeof(NotMappingAttribute)); | |
| if (DoNotMap != null && DoNotMap.Value == true) | |
| { | |
| continue; | |
| } | |
| //if (!destinationProperty.CanWrite && sourceProperty.CanRead) | |
| //{ | |
| // throw new MappingException<TSource, TDestination>(ExceptionMessage.MappingException() + "-" + "Set accessor is not accessible on '" + destinationProperty.Name + "'"); | |
| //} | |
| if (destinationProperty.PropertyType == sourceProperty.PropertyType) | |
| { | |
| if (source != null) | |
| { | |
| destinationProperty.SetValue(destination, sourceProperty.GetValue(source, null), null); | |
| } | |
| } | |
| else | |
| { | |
| if (MappingRelations != null) | |
| { | |
| if (HasAggregatesDefined(sourceProperty.PropertyType.ToString())) | |
| { | |
| Type d1 = typeof(Mapper<,>); | |
| Type[] typeArgs = { sourceProperty.PropertyType, destinationProperty.PropertyType }; | |
| Type constructed = d1.MakeGenericType(typeArgs); | |
| Object[] _parameterss = new Object[1]; | |
| _parameterss[0] = MappingRelations; | |
| object o = Activator.CreateInstance(constructed, _parameterss); | |
| MethodInfo theMethod = constructed.GetMethod("MapClassReflection"); | |
| object[] _parameters = new object[2]; | |
| _parameters[0] = sourceProperty.GetValue(source, null); | |
| _parameters[1] = destinationProperty.GetValue(destination, null); | |
| theMethod.Invoke(o, _parameters); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| catch (System.Exception ex) | |
| { | |
| throw new MappingException<TSource, TDestination>(ExceptionMessage.MappingException() + "-" + ex.Message); | |
| } | |
| } | |
| } | |
| private bool HasAggregatesDefined(string sourceTypeName) | |
| { | |
| return (string.IsNullOrEmpty(MappingRelations.Where(x => x.Key == sourceTypeName).FirstOrDefault().Value)) ? false : true; | |
| } | |
| /// <summary> | |
| /// Loop inside the DestinationType and return the PropertyName if there is a matching Proprety with the sourceType | |
| /// For matching it have to be the same Name | |
| /// </summary> | |
| /// <param name="sourcePropertyName"></param> | |
| /// <param name="destinationType"></param> | |
| /// <returns></returns> | |
| private static string LookupForPropertyInDestinationType(string sourcePropertyName, Type destinationType) | |
| { | |
| foreach (PropertyInfo property in destinationType.GetProperties()) | |
| { | |
| if (property.Name == sourcePropertyName) | |
| { | |
| return sourcePropertyName; | |
| } | |
| } | |
| return null; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment