От AutoMapper до Emit Mapper - PullRequest
       50

От AutoMapper до Emit Mapper

4 голосов
/ 08 декабря 2010

Я недавно обнаружил AutoMapper для соединения ViewModels и моих реальных объектов БД. Я использую его так, как описано здесь: http://automapper.codeplex.com/wikipage?title=Projection&referringTitle=Home

Я обнаружил, что Emit Mapper: :), но я не могу найти ничего похожего (где я могу указать собственные правила проецирования):

    .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date))

Заранее спасибо!

1 Ответ

2 голосов
/ 03 января 2012

Для Записи это лучшее решение, которое я натолкнулся на то, как это сделать:

http://emitmapper.codeplex.com/discussions/259655

Проверьте решение в последнем сообщенииЭто работает очень хорошо.

Обновление: код для дальнейшего использования:

public class ExtDefaultMapConfig<TSrc, TDst> : DefaultMapConfig
    {
        private readonly Dictionary<string, Func<TSrc, object>> _properties = new Dictionary<string, Func<TSrc, object>>();

        public ExtDefaultMapConfig<TSrc, TDst> ForMember(string property, Func<TSrc, object> func)
        {
            if (!_properties.ContainsKey(property))
                _properties.Add(property, func);
            return this;
        }

        public ExtDefaultMapConfig<TSrc, TDst> ForMember(Expression<Func<TDst, object>> dstMember, Func<TSrc, object> func)
        {
            var prop = ReflectionHelper.FindProperty(dstMember);
            return ForMember(prop.Name, func);
        }

        public ExtDefaultMapConfig<TSrc, TDst> Ignore(Expression<Func<TDst, object>> dstMember)
        {
            var prop = ReflectionHelper.FindProperty(dstMember);
            IgnoreMembers<TSrc, TDst>(new[] { prop.Name });
            return this;
        }

        public override IMappingOperation[] GetMappingOperations(Type from, Type to)
        {
            var list = new List<IMappingOperation>();
            list.AddRange(base.GetMappingOperations(from, to));
            list.AddRange(
                    FilterOperations(
                        from,
                        to,
                        ReflectionUtils.GetPublicFieldsAndProperties(to)
                        .Where(f => _properties.ContainsKey(f.Name))
                        .Select(
                            m =>
                            (IMappingOperation)new DestWriteOperation
                            {
                                Destination = new MemberDescriptor(m),
                                Getter =
                                    (ValueGetter<object>)
                                    (
                                        (value, state) =>
                                            {
                                                Debug.WriteLine(string.Format("Mapper: getting value of field or property {0}", m.Name));
                                                return ValueToWrite<object>.ReturnValue(_properties[m.Name]((TSrc) value));
                                            }
                                    )
                            }
                        )
                    )
                );

            return list.ToArray();
        }
    }

    class ReflectionHelper
    {
        public static MemberInfo FindProperty(LambdaExpression lambdaExpression)
        {
            Expression expression = lambdaExpression;
            bool flag = false;
            while (!flag)
            {
                switch (expression.NodeType)
                {
                    case ExpressionType.Convert:
                        expression = ((UnaryExpression)expression).Operand;
                        break;
                    case ExpressionType.Lambda:
                        expression = ((LambdaExpression)expression).Body;
                        break;
                    case ExpressionType.MemberAccess:
                        MemberExpression memberExpression = (MemberExpression)expression;
                        if (memberExpression.Expression.NodeType != ExpressionType.Parameter && memberExpression.Expression.NodeType != ExpressionType.Convert)
                            throw new ArgumentException(string.Format("Expression '{0}' must resolve to top-level member.", lambdaExpression), "lambdaExpression");
                        return memberExpression.Member;
                    default:
                        flag = true;
                        break;
                }
            }
            return null;
        }

        public static object GetValue(string property, object obj)
        {
            PropertyInfo pi = obj.GetType().GetProperty(property);
            return pi.GetValue(obj, null);
        }
    }  
...