从AutoMapper到Emit Mapper

时间:2010-12-07 21:58:35

标签: asp.net-mvc-2 dto projection emitmapper

我最近发现了用于桥接ViewModels和我的实际数据库对象的AutoMapper。我按照这里描述的方式使用它:http://automapper.codeplex.com/wikipage?title=Projection&referringTitle=Home

我发现了Emit Mapper :),但我找不到任何类似的(我可以指定自定义投影规则):

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

提前致谢!

1 个答案:

答案 0 :(得分:2)

对于记录,这是我遇到的最佳解决方案:

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);
        }
    }