Pass Objects to AutoMapper Mapping

后端 未结 5 827
囚心锁ツ
囚心锁ツ 2020-12-04 18:03

I am working with AutoMapper and some of the values for the entity being mapped to are variables in my current method. I have tried to Google it but to no avail. Can I pass

5条回答
  •  悲哀的现实
    2020-12-04 18:34

    Objects can be passed to the resolver with the Items Dictionary option. The standard API to do this is pretty verbose (as seen in the accepted answer) but can be simplified nicely using a few extension methods:

    /// 
    /// Map using a resolve function that is passed the Items dictionary from mapping context
    /// 
    public static void ResolveWithContext(
        this IMemberConfigurationExpression memberOptions, 
        Func, TDest, TMember, TResult> resolver
    ) {
        memberOptions.ResolveUsing((src, dst, member, context) => resolver.Invoke(src, context.Items, dst, member));
    }
    
    public static TDest MapWithContext(this IMapper mapper, TSource source, IDictionary context, Action> optAction = null) {
        return mapper.Map(source, opts => {
            foreach(var kv in context) opts.Items.Add(kv);
            optAction?.Invoke(opts);
        });
    }
    

    Which can be used like this:

    // Define mapping configuration
    Mapper.CreateMap()
        .ForMember(
            d => d.ImageId,
            opt => opt.ResolveWithContext(src, items, dst, member) => items["ImageId"])
        );
    
    // Execute mapping
    var context = new Dictionary { { "ImageId", ImageId } };
    return mapper.MapWithContext(source, context);
    

    If you have an object that you commonly need to pass to mapper resolvers (for example, the current user), you can go one step further and define more specialized extensions:

    public static readonly string USER_CONTEXT_KEY = "USER";
    
    /// 
    /// Map using a resolve function that is passed a user from the
    /// Items dictionary in the mapping context
    /// 
    public static void ResolveWithUser(
        this IMemberConfigurationExpression memberOptions,
        Func resolver
    ) {
        memberOptions.ResolveWithContext((src, items, dst, member) =>
            resolver.Invoke(src, items[USER_CONTEXT_KEY] as User));
    }
    
    /// 
    /// Execute a mapping from the source object to a new destination
    /// object, with the provided user in the context.
    /// 
    public static TDest MapForUser(
        this IMapper mapper,
        TSource source,
        User user,
        Action> optAction = null
    ) {
        var context = new Dictionary { { USER_CONTEXT_KEY, user } };
        return mapper.MapWithContext(source, context, optAction);
    }
    

    Which can be used like:

    // Create mapping configuration
    Mapper.CreateMap()
        .ForMember(d => d.Foo, opt => opt.ResolveWithUser((src, user) src.Foo(user));
    
    // Execute mapping
    return mapper.MapWithUser(source, user);
    

提交回复
热议问题