代码之家  ›  专栏  ›  技术社区  ›  Sven Grosen

c更改linq表达式的返回值

  •  4
  • Sven Grosen  · 技术社区  · 7 年前

    一些背景:这只是我在玩 Expression 第一次使用对象,并尝试简化在我们的某个应用程序中可能使用的内容。我已经做了十多年的C开发人员,但直到现在我才有理由跳入表达式。

    我正在尝试生成一个扩展方法来修改表达式的返回值。更具体地说,我正在尝试添加一个扩展方法来在创建automapper映射时使用。

    实例图:

    map.CreateMap<Widget, WidgetModel>()
       .ForMember(x => x.Count, opts => opts.MapFrom(src => src.Count + 1));
    

    我要做的是创建一个扩展方法,这样我就不必这么做了 + 1 任何地方都可以这样写:

    map.CreateMap<Widget, WidgetModel>()
       .Increment(x => x.Count, src => src.Count);
    

    并拥有 Increment() + 1 为了我。

    我环顾四周,意识到 ExpressionVisitor 可能是我需要的,但我不确定从那里去哪里?

    这个 question 看起来很相似,但我无法将该工作翻译成我的用例。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Victor Procure sachin BR    7 年前

    你可以使用 Expression.Increment 而不是做+1。 或者我们可以让它真正通用。

    像这样:

    void Main()
    {
        var mapperConfiguraiton = 
            new MapperConfiguration(cfg => 
                cfg.CreateMap<Widget, WidgetModel>()
                   .Increment(x => x.CountD, src => src.Count)
                   .ToUpper(x => x.Name, src=>src.Name));
    
        var widget = new Widget {Count = 3, Name="Jimmy"};
        var mapper = mapperConfiguraiton.CreateMapper();
    
        var model = mapper.Map<WidgetModel>(widget);
    }
    
    public class Widget {
        public int Count {get; set;}
        public string Name {get;set;}
    }
    
    public class WidgetModel {
        public int Count {get; set;}
        public string Name {get;set;}
    }
    
    public static class MapperExtensions {
        public static IMappingExpression<TSource, TDestination> Increment<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression, 
            Expression<Func<TDestination, int>> destinationMember, 
            Expression<Func<TSource, int>> sourceMember) 
        {
            return expression.CustomAction(destinationMember, sourceMember, s => s + 1);
         }
    
        public static IMappingExpression<TSource, TDestination> ToUpper<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression, 
            Expression<Func<TDestination, string>> destinationMember, 
            Expression<Func<TSource, string>> sourceMember)
        {
            return expression.CustomAction(destinationMember, sourceMember, s => s.ToUpper());
        }
    
    
        public static IMappingExpression<TSource, TDestination> CustomAction<TSource, TDestination, TDestinationMember, TSourceMember>(
            this IMappingExpression<TSource, TDestination> expression, 
            Expression<Func<TDestination, TDestinationMember>> destinationMember, 
            Expression<Func<TSource, TSourceMember>> sourceMember, 
            Expression<Func<TSourceMember, TDestinationMember>> transform)
        {
           var sourceMemberExpression = (MemberExpression)sourceMember.Body;        
           var sourceParameter = Expression.Parameter(typeof(TSource));
    
           var expr = Expression.Invoke(transform, 
                                    Expression
                                        .MakeMemberAccess(sourceParameter, sourceMemberExpression.Member));
    
            var lambda = (Expression<Func<TSource,TSourceMember>>)
                Expression.Lambda(expr, sourceParameter);
    
            var newExpression = expression.ForMember(
                 destinationMember, 
                 opts => opts.MapFrom(lambda));
    
            return newExpression;
        }
    }
    

    输出:

    widget.Count = 3
    widget.Name = "Jimmy"
    
    model.Count = 4
    model.Name = "JIMMY"
    
    推荐文章