Mapping de données

Contenu du snippet

Voici un exemple de mapper :

 
/* 

 Author : Sébastien Ferrand (Soat Experts) - @sebmafate 
 Url  : http://blog.soat.fr/author/sebastien-ferrand/ 
 Date : october 5, 2012 
 Company : Soat (http://www.soat.fr) 


*/ 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Linq.Expressions; 
  
namespace SF.Mapping 
{ 
    public abstract class Mapper<TEntity, TModel> 
        where TEntity : class, new() 
        where TModel : class, new() 
    { 
        /// <summary> 
        /// Gets the bindings. 
        /// </summary> 
        /// <remarks></remarks> 
        public List<Tuple<Expression<Func<TEntity, object>>, Expression<Func<TModel, object>>>> Bindings { get; private set; } 
  
        /// <summary> 
        /// Initializes a new instance of the <see cref="Mapper<TEntity, TModel>"></see> class. 
        /// </summary> 
        /// <remarks></remarks> 
        public Mapper() { 
            this.Bindings = new List<Tuple<Expression<Func<TEntity, object>>, Expression<Func<TModel, object>>>>(); 
             
            this.InitializeBinding(); 
        } 
  
        /// <summary> 
        /// Initializes the binding. 
        /// </summary> 
        /// <remarks></remarks> 
        protected abstract void InitializeBinding(); 
  
        /// <summary> 
        /// Adds the binding. 
        /// </summary> 
        /// <param name="entity">The entity.</param> 
        /// <param name="model">The model.</param> 
        /// <param name="thrownOnTypeMismatch">if set to <c>true</c> thrown on type mismatch.</param> 
        /// <remarks></remarks> 
        public void AddBinding(Expression<Func<TEntity, object>> entity, Expression<Func<TModel, object>> model, bool thrownOnTypeMismatch = true) { 
            if (thrownOnTypeMismatch && 
                entity.ReturnType != model.ReturnType) { 
                    throw new Exception("Types are differents !"); 
            } 
  
            this.Bindings.Add(new Tuple<Expression<Func<TEntity, object>>, Expression<Func<TModel, object>>>(entity, model)); 
        } 
  
        /// <summary> 
        /// Maps to entity. 
        /// </summary> 
        /// <param name="model">The model.</param> 
        /// <returns></returns> 
        /// <remarks></remarks> 
        public TEntity MapToEntity(TModel model) { 
            var entity = new TEntity(); 
            entity = this.MapToEntity(model); 
  
            return entity; 
        } 
  
        /// <summary> 
        /// Maps to entity. 
        /// </summary> 
        /// <param name="model">The model.</param> 
        /// <param name="entity">The entity.</param> 
        /// <returns></returns> 
        /// <remarks></remarks> 
        public TEntity MapToEntity(TModel model, TEntity entity) { 
            //var entity = new TEntity(); 
  
            foreach (var binding in this.Bindings) 
            { 
                var action = CreateAssignAction(binding, MappingType.ModelToEntity); 
  
                action(entity, model); 
            } 
  
            this.OnMappingToEntityEnded(model, entity); 
  
            return entity; 
        } 
  
        /// <summary> 
        /// Maps to model. 
        /// </summary> 
        /// <param name="entity">The entity.</param> 
        /// <returns></returns> 
        /// <remarks></remarks> 
        public TModel MapToInput(TEntity entity) { 
            var model = new TModel(); 
  
            foreach (var binding in this.Bindings) { 
                var action = CreateAssignAction(binding, MappingType.EntityToModel); 
  
                action(entity, model); 
            } 
  
            this.OnMappingToInputEnded(entity, model); 
  
            return model; 
        } 
  
        /// <summary> 
        /// Called when [mapping to input ended]. 
        /// </summary> 
        /// <param name="entity">The entity.</param> 
        /// <param name="model">The model.</param> 
        /// <remarks></remarks> 
        protected virtual void OnMappingToInputEnded(TEntity entity, TModel model) { } 
  
        /// <summary> 
        /// Called when [mapping to entity ended]. 
        /// </summary> 
        /// <param name="model">The model.</param> 
        /// <param name="entity">The entity.</param> 
        /// <remarks></remarks> 
        protected virtual void OnMappingToEntityEnded(TModel model, TEntity entity) { } 
  
        /// <summary> 
        /// Creates the assign action. 
        /// </summary> 
        /// <param name="binding">The binding.</param> 
        /// <param name="mappingType">Type of the mapping.</param> 
        /// <returns></returns> 
        /// <remarks></remarks> 
        private Action<TEntity, TModel> CreateAssignAction(Tuple<Expression<Func<TEntity, object>>, Expression<Func<TModel, object>>> binding, MappingType mappingType) 
        { 
            string propertyNamea, propertyNameb; 
            // Récupération du nom de la propriété de la propriété "a" 
            if (binding.Item1.Body is MemberExpression) 
            { 
                propertyNamea = ((MemberExpression)binding.Item1.Body).Member.Name; 
            } 
            else 
            { 
                propertyNamea = ((binding.Item1.Body as UnaryExpression).Operand as MemberExpression).Member.Name; 
            } 
  
            // Récupération du nom de la propriété de la propriété "b" 
            if (binding.Item2.Body is MemberExpression) 
            { 
                propertyNameb = ((MemberExpression)binding.Item2.Body).Member.Name; 
            } 
            else 
            { 
                propertyNameb = ((binding.Item2.Body as UnaryExpression).Operand as MemberExpression).Member.Name; 
            } 
  
            // Construction des Expressions contenant les parametres 
            var parama = Expression.Parameter(typeof(TEntity), "a"); 
            var paramb = Expression.Parameter(typeof(TModel), "b"); 
  
            // Construction des expressions : a."propriété" 
            var propertyOfa = Expression.PropertyOrField(parama, propertyNamea); 
            var propertyOfb = Expression.PropertyOrField(paramb, propertyNameb); 
  
            // Construction de la lambda a = b (suivant context) 
            // ou si les types sont différents : a = Convert(b) 
            Expression lambda; 
            if (mappingType == MappingType.ModelToEntity) 
            { 
                if (propertyOfa.Type == propertyOfb.Type) 
                { 
                    lambda = Expression.Assign(propertyOfa, propertyOfb); 
                } 
                else 
                { 
                    lambda = Expression.Convert(propertyOfb, propertyOfa.Type); 
                    lambda = Expression.Assign(propertyOfa, lambda); 
                } 
            } 
            else 
            { 
                if (propertyOfa.Type == propertyOfb.Type) 
                { 
                    lambda = Expression.Assign(propertyOfb, propertyOfa); 
                } 
                else 
                { 
                    lambda = Expression.Convert(propertyOfa, propertyOfb.Type); 
                    lambda = Expression.Assign(propertyOfb, lambda); 
                } 
            } 
  
            // Création de la lambda : (a,b) => b = a 
            var t = Expression.Lambda<Action<TEntity, TModel>>(lambda, parama, paramb); 
            var action = t.Compile(); 
  
            return action; 
        } 
  
  
        private enum MappingType 
        { 
            EntityToModel, 
            ModelToEntity 
        } 
    } 
} 


Ce code est lié à l'article suivant : http://blog.soat.fr/2012/10/mapping-dentites-en-net/

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.