1

所以我正在使用 AutoMapper 库,并且试图了解 AutoMapper 如何从源属性映射到目标属性。我想我只是缺少 C# 表达式语法/Linq 支持的关键部分。如果有人可以向我解释这里到底发生了什么,我将不胜感激。

下面是一些 AutoMapper 配置代码的示例:

Mapper.CreateMap<SourceModel, DestinationModel>()
                .ForMember(dest => dest.Summary, opt => opt.MapFrom(src => src.Summary))
                .ForMember(dest => dest.Year, opt => opt.MapFrom(src => src.Year));

我对这条线最困惑dest => dest.Summary......究竟是如何src.Summary映射到的dest.Summary?评估表达式如何dest.Summary告诉 AutomMapper 映射到该属性?我猜有一些我不理解或缺少的强大的 lambda/表达式功能。

谢谢!

4

2 回答 2

2

Automapper 只是获取有关您希望映射的类型和PropertyInfo要匹配的属性的信息。如果您想了解它在做什么,请尝试使用以下方法:

public static class PropertyExtensions
{
    public static System.Reflection.PropertyInfo ToPropertyInfo<T, TProperty>(this Expression<Func<T, TProperty>> propExpression) where T : class
    {
        if (propExpression == null)
            throw new ArgumentNullException("propExpression");
        var expr = propExpression.Body as MemberExpression;
        if (expr == null)
            throw new ArgumentException("Property expression is not a member expression.", "propExpression");
        var propInfo = expr.Member as System.Reflection.PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException("Member expression is not for a property.", "propExpression");
        return propInfo;
    }
}
public static class TestIt<T> where T : class
{
    public static void PrintProperty<TProperty>(Expression<Func<T, TProperty>> propExpression)
    {
        Console.WriteLine(propExpression.ToPropertyInfo());
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestIt<string>.PrintProperty(s => s.Length);
    }
}
于 2013-08-27T21:25:43.123 回答
1

具体你在问什么有点不清楚,有几个部分:

  • 流畅的界面。当你调用CreateMap()它时,它会返回类似IFluentInterface<TSource, TDestination>. 这是定义映射的主界面。这个接口的大多数成员也会返回这个接口,它允许你进行多次.ForMember()调用

    • CreateMap()调用还设置通用类型。您传递的类型将应用于接口的所有相关成员,为您提供强类型接口(“封闭泛型”)。如果没有这个调用,likedest => dest.Summary是不可能的(您可能必须按名称指定它们,这很脆弱)。
  • ForMember()调用有两个参数。

    • 第一个很可能是Expression<Func<TDestination, object>>. 这是一个拗口,但它指定您可以针对返回对象的TDestination类型(由前面的CreateMap()调用关闭)提供一个 Lamdda 表达式。在此方法中,它可能会将指定的对象解析为 MemberInfo,这让 automapper 可以检索指定成员的元数据和值。

    • 第二个成员是另一个 AutoMapper 类型;它将是一种用于指示 AutoMapper 如何为指定成员设置值的类型。可以提供一个参数,例如opt.MapFrom<TSource>()您的示例中的调用,或者可能提供其他人来执行诸如使用常量值之类的操作。

这些调用可能在 AutoMapper 初始化期间用于定义从一种类型到另一种类型的映射的配置。基本上这些是说明;AutoMapper 可能有也可能没有单独的代码集,这些代码遵循这些指令来执行实际映射。


这是另一个 SO question,它显示了调用 like 的内部结构是如何ForMember(dest => dest.Summary) 实现的。这包括查找MemberInfo指定成员的。

这是有关 Fluent Interfaces的一些基本信息/

于 2013-08-27T21:08:12.720 回答