我正在使用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
课程中创建...
我怎么能解决这个问题?谢谢!
答案 0 :(得分:1)
您的所有个人资料都不正确。您需要在个人资料上调用CreateMap,而不是Mapper.CreateMap:
public class PersonProfile : Profile
{
protected override void Configure()
{
CreateMap<Person, PersonDTO>().ReverseMap();
}
}