如何在基于 ASP.NET Core 5 的多层 Web 应用中初始化 AutoMapper?

How to initialize AutoMapper in a multi-layer web application based on ASP.NET Core 5?

我只是第一次尝试在项目中使用 AutoMapper。我的解决方案包括以下项目:

在较旧的项目中,我总是直接使用脚手架 classes 来处理所有事情。在大多数情况下,这工作得很好,但由于各种不同的原因我不再想这样做(例如,因为 classes 并不总是按照我希望的方式命名,而且 modifying/extending 它们也很困难,有时甚至是不可能的)。 因此,我想使用 AutoMapper 将脚手架 classes 映射到 classes 中,我可以在不依赖 EFCore 的情况下完全控制它。

我已经将 AutoMapper NuGet 包添加到 DataAccess 项目中,因为这是我希望进行映射的地方。现在我的第一个问题是:在哪里以及如何初始化它? 在教程中,我经常看到人们在 Startup.cs 文件中初始化它,但是由于我在 Web 应用程序项目中没有引用 AutoMapper,所以我不能这样做。

显然,我还需要能够在 DataAccess 项目中的不同 classes 中使用 AutoMapper 函数,那么如何在那些 classes 中获取对它的引用?在 examples/tutorials 这通常是通过依赖注入完成的,但这似乎不太适合我当前的项目架构。但是,如果在我的解决方案中有通过 DI 执行此操作的简单方法,请告诉我,因为我仍然不完全了解如何在多项目解决方案中使用 DI。

这是我想如何使用 AutoMapper 的示例:

Web 应用程序中的控制器方法:

[HttpGet]
public IEnumerable<Project> GetProjects()
{
    using (ProjectManager projectManager = new ProjectManager())
    {
        return projectManager.GetProjects();
    }
}

BusinessLogic 项目中的经理class(已简化):

public List<Project> GetProjects()
{
    return projectDataAccessor.GetProjects();
}

DataAccess 项目中的访问器 class:

public List<Project> GetProjects()
{
    List<Project> projects = new List<Project>();

    foreach (TblProject tblProject in context.TblProjects)
    {
        Project project = <map tblProject into type Project>; // ToDo
        projects.Add(project);
    }

    return projects;
}

如何初始化和使用 AutoMapper 才能执行此类操作?

如果您真的不想使用依赖注入,您可以使用静态引导程序class来设置映射并访问映射器实例:

// DataAccess project
public static class MapperBootstrapper
{
    private static IMapper _instance;
    internal static IMapper Instance => _instance;
    
    public static void Configure()
    {
        if (_instance != null)
            throw new InvalidOperationException("Already configured");
        
        var config = new MapperConfiguration(
            cfg =>
            {
                cfg.AddProfile<ProjectProfile>();
                // Add more profiles and other mapping
            });
        _instance = config.CreateMapper();
    }
}

使用配置文件,您可以对相关的映射逻辑进行分组,例如与 Project 模型相关的映射:

// DataAccess project
public class ProjectProfile : Profile
{
    public ProjectProfile()
    {
        CreateMap<ProjectEntity, Model.Project>()
            .ForMember(
                dest => dest.FullName,
                opt => opt.MapFrom(src => $"{src.Area}\{src.Name}"));
    }
}

然后在您的 Startup.cs 中,您可以使用引导程序 class 在应用程序的生命周期中尽早设置映射(如果您不希望 WebApplication 项目引用 DataAccess 项目,您将需要在 BusinessLogic 项目中使用中间 class):

public void ConfigureServices(IServiceCollection services)
{
    DataAccess.MapperBootstrapper.Configure();
    // ...
}

在您的 ProjectDataAccessor 中,您可以像这样使用映射器:

public List<Model.Project> GetProjects()
{
    var dbCollection = // Get data from the source
    
    return MapperBootstrapper.Instance
        .Map<List<Model.Project>>(dbCollection);
}

示例基于一些虚拟模型:

// DataAccess project
public class ProjectEntity
{
    public Guid ID { get; set; }
    public string Area { get; set; }
    public string Name { get; set; }
}

// Model project
public class Project
{
    public Guid ID { get; set; }
    public string FullName { get; set; }
}

要查看实际示例,请查看 this fiddle