cezarypiatek / MappingGenerator

:arrows_counterclockwise: "AutoMapper" like, Roslyn based, code fix provider that allows to generate mapping code in design time.
https://marketplace.visualstudio.com/items?itemName=54748ff9-45fc-43c2-8ec5-cf7912bc3b84.mappinggenerator
MIT License
1.03k stars 120 forks source link

Feature request: mapping for get only lists #112

Open jorisdebock opened 4 years ago

jorisdebock commented 4 years ago

Could we add a mapping option for get only lists?

It is useful for when an object is doing the list initialization themself and only exposing a getter for the list. In my case, I am using protobuf/grpc which generates types with only a getter for the list. And filling the list should be done with Add/Addrange, it would be nice if the mapping for this can be generated.

e.g. the following objects

    public class Hello
    {
        public string Message { get; set; }
        public List<string> Names { get; set; }
    }
    public class Hello3
    {
        public string Message { get; set; }
        public List<string> Names { get; } = new List<string>();
    }

   [MappingInterface]
    public interface IGreeterServiceMapper
    {
        Hello3 MapHello3(Hello hello);
    }

current generated result

        public virtual Hello3 MapHello3(Hello hello)
        {
            return new GrpcService1.Hello3()
            {
                Message = hello.Message
            };
        }

would like to have the following code generated

        public virtual Hello3 MapHello3(Hello hello)
        {
            var hello3 = new GrpcService1.Hello3()
            {
                Message = hello.Message
            };
            hello3.Names.AddRange(hello.Names);
            return hello3;
        }
cezarypiatek commented 4 years ago

Right now it's impossible without huge redesign. Mappings for methods with signature Hello3 MapHello3(Hello hello) are generated as a single expression. To achieve the same result as you propose a multi-statement output is required. This is on my TODO list but I can't promise if or when this will be implemented.

jorisdebock commented 4 years ago

@cezarypiatek I can make a pull request of my code (wip), this already generates the above code without breaking any other tests.

cezarypiatek commented 4 years ago

cool, please do that, I will take a look at that

cezarypiatek commented 4 years ago

@cezarypiatek can you check if the following syntax works correctly? At least it doesn't give me any syntax errors:

public virtual Hello3 MapHello3(Hello hello)
        {
            return new GrpcService1.Hello3()
            {
                Message = hello.Message,
                Names = {
                    hello.Names
               }
            };
        }

UPDATE: I've tested it by myself and it's working. I think Mapping Generator should implement this syntax for collection without setters. I think there is a similar problem for other properties (complex object) without setters.

UPDATE: This kind of assignment is valid for types that implement IEnumerable and contain a method void Add(IEnumerable<T> elements)