给出这些源类(在EFCore应用程序中使用)
class StudentCourse
{
public int StudentId { get; set; }
public int CourseId { get; set; }
}
class Student
{
public virtual ICollection<StudentCourse> Courses { get; set; }
}
以及以下Protobuf
消息
message StudentDto {
repeated int32 courseIds = 1;
}
如何使用Student.Courses
将StudentDto.CourseIds
映射到AutoMapper
?
到目前为止,我尝试了以下方法:
class StudentProfile : Profile
{
class Converter : IValueConverter<ICollection<StudentCourse>, RepeatedField<int>>
{
public RepeatedField<int> Convert(ICollection<StudentCourse> sourceMember, ResolutionContext context)
{
return new RepeatedField<int> { sourceMember.Select(x => x.CourseId) };
}
}
public StudentProfile()
{
CreateMap<Student, StudentDto>()
.ForMember(dst => dst.CourseIds, o => o.MapFrom(src => src.Courses.Select(x => x.CourseId)));
//.ConvertUsing(student => new StudentDto{CourseIds = { student.Courses.Select(x => x.CourseId)}});
//.ForMember(dst => dst.CourseIds, o => o.ConvertUsing(new Converter(), src => src.Courses));
}
}
class Program
{
static void Main(string[] args)
{
var student = new Student
{
Courses = new List<StudentCourse>
{
new StudentCourse { CourseId = 1, StudentId = 1 },
new StudentCourse { CourseId = 6, StudentId = 1 },
new StudentCourse { CourseId = 11, StudentId = 1 }
}
};
IMapper mapper = new Mapper(new MapperConfiguration(cfg => cfg.AddProfile(new StudentProfile())));
var mapped = mapper.Map<StudentDto>(student);
// Expecting: {{ "courseIds": [ 1, 6, 11 ] }}
// Actually: {{ }}
}
}
ConvertUsing
中的StudentProfile
语句可以正常工作并正确映射成员,但是由于我在项目中使用的类要复杂得多,所以这实际上是我要使用的最后一个选项。
你们中有人知道这个问题的原因和可能的解决方法吗?
我正在使用Google.Protobuf 3.7.0
和AutoMapper 8.0.0
。
修改:
我已经检查了执行计划,但是在那里找不到任何错误。
为了完整起见,我将其附在此处:
(src, dest, ctxt) =>
{
StudentDto typeMapDestination;
return (src == null)
? null
: {
typeMapDestination = dest ?? new StudentDto();
try
{
var resolvedValue =
{
try
{
return ((src == null) || ((src.Courses == null) || false))
? null
: src.Courses.Select(x => x.CourseId);
}
catch (NullReferenceException)
{
return null;
}
catch (ArgumentNullException)
{
return null;
}
};
var propertyValue = (resolvedValue == null)
? {
var collectionDestination = (ICollection<int>)((dest == null) ? null : typeMapDestination.CourseIds);
if ((collectionDestination == null) || collectionDestination.IsReadOnly)
{
}
else
{
collectionDestination.Clear();
}
return new RepeatedField<int>();
}
: {
var passedDestination = (dest == null) ? null : typeMapDestination.CourseIds;
var collectionDestination = ((passedDestination == null) || ((ICollection<int>)passedDestination).IsReadOnly)
? new RepeatedField<int>()
: passedDestination;
collectionDestination.Clear();
var enumerator = resolvedValue.GetEnumerator();
while (true)
{
if (enumerator.MoveNext())
{
var item = enumerator.Current;
collectionDestination.Add(item);
}
else
{
break;
}
}
return collectionDestination;
};
return propertyValue;
}
catch (Exception ex)
{
throw new AutoMapperMappingException(
"Error mapping types.",
ex,
AutoMapper.TypePair,
TypeMap,
PropertyMap);
return null;
}
return typeMapDestination;
};
};