Отображение типа прототипа RepeatedField <T> - PullRequest
0 голосов
/ 18 апреля 2019

Учитывая эти исходные классы (используемые в приложении 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;
        };
};
...