为什么我需要创建相同的地图,如果它已经在Automapper中创建

本文关键字:创建 如果 Automapper 地图 为什么 | 更新日期: 2023-09-27 18:17:33

我使用的是Automapper 4.1.1,因为。net Framework 4.0需要。我决定在每个应用程序启动时调用Automapper配置。所以,我的类看起来像:

// AutoMapper Business Logic Layer Configuration
public class PersonProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Person, PersonDTO>().ReverseMap();
    }
}
public class PhotoProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Photo, PhotoDTO>().ReverseMap();
    }
}
public class DicProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Dic, DicDTO>().ReverseMap();
    }
}
public class SubjectProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Subject, SubjectDTO>().ReverseMap();
    }
}
public class PhotoSubjectIgnoreProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Person, PersonDTO>()
              .ForMember(ph => ph.Photos, opt => opt.Ignore())
              .ForMember(sub => sub.Subjects, opt => opt.Ignore());
    }
}
public class PhotoSubjectIncludeProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<Person, PersonDTO>()
              .ForMember(pe => pe.Photos, opt => opt.MapFrom(p => p.Photos))
              .ForMember(dto => dto.Subjects, opt => opt.MapFrom(p => p.Subjects));
    }
}
// AutoMapper Presentation Layer Configuration
public class PersonViewProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<PersonDTO, PersonViewModel>()
              .ForMember(model => model.Photos, opt => opt.MapFrom(dto => dto.Photos))
              .ForMember(model => model.Subjects, opt => opt.MapFrom(dto => dto.Subjects))
              .ForMember(model => model.BirthdaySingle, opt => opt.MapFrom(dto => dto.BirthdaySingle.NullIntToNullDateTime("yyyyMMdd")));
        Mapper.CreateMap<PersonViewModel, PersonDTO>()
              .ForMember(dto => dto.Photos, opt => opt.MapFrom(model => model.Photos))
              .ForMember(dto => dto.Subjects, opt => opt.MapFrom(dto => dto.Subjects))
              .ForMember(dto => dto.BirthdaySingle, opt => opt.MapFrom(model => model.BirthdaySingle.NullDateTimeToNullInt("yyyyMMdd")));
    }
}
public class PersonShortViewProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<PersonDTO, PersonListViewModel.PersonShortViewModel>()
            .IgnoreAllNonExisting().ForMember(model => model.Birthday,opt => opt.MapFrom(dto => dto.BirthdaySingle.NullIntToNullDateTime("yyyyMMdd")));
    }
}
public class PhotoViewProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<PhotoDTO, PhotoViewModel>().ReverseMap();
    }
}
public class DicViewProfile:Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<DicDTO, DicViewModel>().ForSourceMember(dto => dto.Id, opt => opt.Ignore());
        Mapper.CreateMap<DicViewModel, DicDTO>().ForMember(dto => dto.Id, opt => opt.Ignore());
    }
}
public class SubjectViewProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<SubjectDTO, SubjectViewModel>().ForSourceMember(dto => dto.Id, opt => opt.Ignore());
        Mapper.CreateMap<SubjectViewModel, SubjectDTO>().ForMember(dto => dto.Id, opt => opt.Ignore());
    }
}

收集整个应用程序中的配置文件的类:

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(configuration =>
                          GetConfiguration(Mapper.Configuration)
            );
        Mapper.AssertConfigurationIsValid();
    }
    private static void GetConfiguration(IConfiguration configuration)
    {
        // Interesting thing: we need to use order by because we need photo mapping to be before Person mappings
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        var allTypes = assemblies.SelectMany(assembly => assembly.GetExportedTypes());
        var profiles = allTypes.Where(type => typeof(Profile).IsAssignableFrom(type) && !type.IsAbstract && type.IsSubclassOf(typeof(Profile))).ToArray();
        foreach (var profile in profiles)
        {
            configuration.AddProfile(Activator.CreateInstance(profile) as Profile);
        }
    }
}

Program.cs类中调用main函数:

internal static class Program
{
    /// <summary>
    /// Главная точка входа для приложения.
    /// </summary>
    [STAThread]
    private static void Main()
    {
        AutoMapperConfiguration.Configure();
        // ...
    }
}

我有一个方法:

/// <summary>
/// Get elements of type PersonDTO using paging settings
/// </summary>
/// <param name="pageNumber">Page number to get</param>
/// <param name="pageSize">Rows per page</param>
/// <returns></returns>
public IQueryable<PersonDTO> GetPersons(int pageNumber, int pageSize)
{
    if (pageNumber < 1)
    {
        throw new ValidationException("Початкове значення має бути більше 0.", "");
    }
    if (pageSize < 1)
    {
        throw new ValidationException("Кількість записів має бути більше 0.", "");
    }
    PageInfo.TotalItems = Database.Persons.CountAll();
    PageInfo.CurrentPage = pageNumber;
    PageInfo.PageSize = pageSize;
    // применяем автомаппер для проекции одной коллекции на другую
    /*Mapper.CreateMap<Person, PersonDTO>()
            .ForMember(ph => ph.Photos, opt => opt.Ignore())
            .ForMember(sub => sub.Subjects, opt => opt.Ignore());*/
    return Database.Persons.GetAll((pageNumber - 1) * pageSize, pageSize).ProjectTo<PersonDTO>();
}

我得到这个错误:

Message:
Value cannot be null.
Parameter name: source
ParamName:
    source
Source:
    System.Core
StackTrace:
   at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
   at lambda_method(Closure , Person )
   at System.Linq.Enumerable.<>c__DisplayClass7_0`3.<CombineSelectors>b__0(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Windows.Forms.BindingSource.GetListFromEnumerable(IEnumerable enumerable)
   at System.Windows.Forms.BindingSource.ResetList()
   at System.Windows.Forms.BindingSource.set_DataSource(Object value)
   at Reestr.WinForms.Views.FrmMain.BindGrid(Int32 pageIndex, Expression`1 predicate) in B:'Programming'Visual Studio 2012'Projects'Reestr_2'Reestr.WinForms'Views'FrmMain.cs:line 270
TargetSite:
    {System.Collections.Generic.IEnumerable`1[TResult] Select[TSource,TResult](System.Collections.Generic.IEnumerable`1[TSource], System.Func`2[TSource,TResult])}
InnerException: null

但是!如果我取消注释Mapper.CreateMap行,这个错误消失,一切工作正常。不明白为什么会这样,因为我已经在PhotoSubjectIgnoreProfile类中创建了这个地图。方法:

也是同样的情况
public PersonDTO GetPerson(long id)
{
    var person = Database.Persons.GetById(id);
    if (person == null)
    {
        throw new ValidationException("Об'єкт не знайдено.", "");
    }
    // применяем автомаппер для проекции Person на PersonDTO
    /*Mapper.CreateMap<Person, PersonDTO>()
        .ForMember(pe => pe.Photos, opt => opt.MapFrom(p => p.Photos))
        .ForMember(pe => pe.Subjects, opt => opt.MapFrom(p => p.Subjects));*/
    return Mapper.Map<PersonDTO>(person);
}

这个地图也已经创建在PhotoSubjectIncludeProfile类…我该如何解决这个问题?谢谢你!

为什么我需要创建相同的地图,如果它已经在Automapper中创建

您的所有配置文件都不正确。你需要在Profile上调用CreateMap,而不是Mapper。CreateMap:

public class PersonProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<Person, PersonDTO>().ReverseMap();
    }
}
相关文章: