LINQ2Vodka
LINQ2Vodka

Reputation: 3036

ConstructProjectionUsing - what am I doing wrong?

Question about the AutoMapper. I am trying to project IQueryable to DTO using construction expression but result always have null's in its fields.

    public class BaseObject { }
    public class DTO { public string Name { get; set; } }

....

            // create map BaseObject-to-DTO
            Mapper.CreateMap<BaseObject, DTO>()
                .ConstructProjectionUsing(s => new DTO
                {
                    Name = "This name will never appear in DTO"
                });

            // create object array with one element
            var objects = new [] { new BaseObject() };

            var result = objects.AsQueryable().ProjectTo<DTO>(); // here Name = null everywhere

Why the Name in results is null?

Upvotes: 1

Views: 923

Answers (2)

Jimmy Bogard
Jimmy Bogard

Reputation: 26765

This is the expected behavior. AutoMapper is trying to build a "Select" projection. A normal source/destination projection without AutoMapper would look something like this in LINQ:

objects.AsQueryable().Select(bo => new DTO { Name = bo.Name });

I go through the source/destination members and build up what's known as a MemberInitExpression in LINQ. That's the construction expression plus member initialization, new + curly brace property assignments.

ConstructProjectionUsing is about replacing just the "new" part of the member init expression: bo => new DTO("I like turtles") { Name = bo.Name }; and not the individual members. For what you're looking for, I'd actually have to merge two member initialization expressions - one that AutoMapper builds from the source/destination properties, and whatever you've put in the configuration. My head hurts thinking about how to do that effectively.

I could probably throw a configuration exception if you tried to do otherwise, or at least had better IntelliSense comments. Feel free to open a GH issue for that!

Upvotes: 1

Ilya Chumakov
Ilya Chumakov

Reputation: 25019

ConstructProjectionUsing accepts constructor only, I guess. It works fine with:

.ConstructProjectionUsing(s => new DTO("This name will never appear in DTO"))

Answer to question "why" lies deep in Automapper sources.

Upvotes: 0

Related Questions