可以使用Items Dictionary 选项将对象传递给解析器。执行此操作的标准 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);