将对象传递给AutoMapper Mapping

本文关键字:AutoMapper Mapping 对象 | 更新日期: 2023-09-27 18:05:49

我正在使用AutoMapper和被映射到的实体的一些值是我当前方法中的变量。我试着用谷歌搜索,但无济于事。我能传递一组键值对或一个对象或其他东西到我的映射,让它使用这些值吗?

后映射修改样例

//comment variable is a Comment class instance
var imageComment = AutoMapper.Mapper.Map<Data.ImageComment>(comment);
//I want to pass in imageId so I dont have to manually add it after the mapping
imageComment.ImageId = imageId;

将对象传递给AutoMapper Mapping

AutoMapper可以开箱即用地处理这个键-值对场景。

Mapper.CreateMap<Source, Dest>()
    .ForMember(d => d.Foo, opt => opt.ResolveUsing(res => res.Context.Options.Items["Foo"]));

运行时:

Mapper.Map<Source, Dest>(src, opt => opt.Items["Foo"] = "Bar");

对上下文项进行深入研究有点啰嗦,不过就这样吧

AutoMapper 9.0.0

从8.0.0版本开始,AutoMapper的API已经更改。这样,ResolveUsingMapFrom就合并了。查看相应的拉取请求以获取更多信息。

概要文件

public class CoreProfile : Profile
{
    public CoreProfile()
    {
        CreateMap<Source, Destination>()
            .ForMember(d => d.Bar,
                opt => opt.MapFrom(
                    (src, dst, _, context) => context.Options.Items["bar"]
                )
            );    
    }
}

var destination = mapper.Map<Destination>(
    source,opt => {
        opt.Items["bar"] = "baz";
    }
);

For Automapper 6.0.2:

简介:

public class CoreProfile : Profile
{
    public CoreProfile()
    {
        CreateMap<Source, Dest>()
            .ForMember(d => d.Foo,
                opt => opt.ResolveUsing(
                    (src, dst, arg3, context) => context.Options.Items["Foo"]
                )
            );
    }
}

映射:

    var result = Mapper.Map<PlanResult>(aa, opt => {
        opt.Items["Foo"] = 2;
        opt.Items["OtherFoo"] = 1000;
    });

对象可以通过Items字典选项传递到解析器。执行此操作的标准API非常冗长(如所接受的答案所示),但可以使用几个扩展方法很好地简化:

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

可以这样使用:

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

如果您有一个通常需要传递给映射器解析器的对象(例如,当前用户),您可以更进一步,定义更专门的扩展:

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

可以这样使用:

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

假设您有以下两个对象:

public class ObjectA {
 public string Property1 { get; set; }
 public int Property2 { get; set; }
}
public class ObjectB {
 public string Property1 { get; set; }
 public int Property2 { get; set; }
}

您想要将现有的ObjectA类型对象复制到ObjectB类型的新对象中,使用AutoMapper您必须这样做:

var objectA = new ObjectA { Property1 = "Hello, World!", Property2 = 1 }
var objectB = new ObjectB();
// Copy data from a to b
AutoMapper.Mapper
  .CreateMap<ObjectA, ObjectB>()
  .BeforeMap((source, dest) => { dest.ImageId = imageId });
AutoMapper.Mapper.Map(objectA, objectB); // source, destination;
// Or:
var objectB = AutoMapper.Mapper.Map<ObjectB>(objectA);