protobuf的RepeatedField <t>类型的映射

时间:2019-04-18 14:26:25

标签: c# automapper protocol-buffers protobuf-net

给出这些源类(在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.CoursesStudentDto.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.0AutoMapper 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;
        };
};

0 个答案:

没有答案