/// <summary> /// <para> Map an object </para> /// </summary> /// <typeparam name="TFrom"> Type to map from </typeparam> /// <typeparam name="TTo"> Type to map to </typeparam> /// <param name="from"> Object to map from </param> /// <param name="toExpression"> Expression for the target </param> /// <param name="context"> Context </param> public void Map <TFrom, TTo>( TFrom from, Expression <Func <TTo> > toExpression, IMapperContext context) where TTo : class { if (toExpression == null) { throw new ArgumentNullException("toExpression"); } if (Equals(from, default(TFrom))) { return; } var toMember = new CollapseMembersExpressionVisitor() .Modify(toExpression); var to = toMember.GetValue(); if (to == null) { to = context.Create <TTo>(); toMember.SetValue(to); } var mapper = Get <TFrom, TTo>(); mapper(from, to, context); context.Update(to); }
/// <summary> /// <para> Map all items </para> /// </summary> /// <typeparam name="TFrom"> Type to map from </typeparam> /// <typeparam name="TTo"> Type to map to </typeparam> /// <param name="from"> Object enumerable to map from </param> /// <param name="toExpression"> Object collection to map to </param> /// <param name="match"> Match function to find objects in the 'to' items given a 'from' item </param> /// <param name="context"> Context </param> public void MapAll <TFrom, TTo>( IEnumerable <TFrom> from, Expression <Func <IEnumerable <TTo> > > toExpression, Func <TFrom, TTo, bool> match, IMapperContext context) where TTo : class { if (toExpression == null) { throw new ArgumentNullException("toExpression"); } if (from == null) { return; } var toMember = new CollapseMembersExpressionVisitor() .Modify(toExpression); var toOriginal = toMember.GetValue(); var toItemType = GetEnumerableElementType(toMember.Type); var toList = toOriginal as IList; if (toOriginal == null || toList == null || toList.IsFixedSize || toList.IsReadOnly) { // create a new member list when null or readonly toList = (IList) (Implements(toMember.Type, typeof(IList)) && !toMember.Type.IsArray ? Activator.CreateInstance(toMember.Type) : Activator.CreateInstance( typeof(Collection <>).MakeGenericType(new[] { toItemType })) ); // set it to the member, knowing it is an IEnumerable<TTo> toMember.SetValue((IEnumerable <TTo>)toList); } // get original 'to' items for matching, and clear from member list var toListOriginal = toOriginal == null ? new List <TTo>() : toOriginal.ToList(); toList.Clear(); // prepare to map each 'from' item var fromItemType = typeof(TFrom); var mapper = Get(fromItemType, toItemType); var mapperMethod = mapper.GetType().GetMethod("Invoke"); foreach (var fromItem in from) { // find the 'to' item or create one var toItem = default(TTo); if (match != null) { toItem = toListOriginal .SingleOrDefault(t => match(fromItem, t)); toListOriginal.Remove(toItem); } if (toItem == null) { toItem = context.Create <TTo>(); } // map mapperMethod.Invoke(mapper, new object[] { fromItem, toItem, context }); toList.Add(toItem); context.Update(toItem); } if (!toListOriginal.Any()) { return; } foreach (var toItem in toListOriginal) { context.Delete(toItem); } }