Mapster icon indicating copy to clipboard operation
Mapster copied to clipboard

Tool generates empty mapper

Open LucaGabi opened this issue 3 years ago • 13 comments

Tool generates empty mapper:

    [AdaptTo("[name]Dto"), GenerateMapper]
    public class Author : BaseEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Book> Books { get; set; }
        public virtual ICollection<AuthorBook> AuthorBooks { get; set; }
    }

    public abstract class BaseEntity
    {
        public BaseEntity()
        {
            CreatedOn = DateTime.Now;
        }

        
        public DateTime CreatedOn { get; set; }
        public DateTime? UpdatedOn { get; set; }
    }

LucaGabi avatar May 17 '21 12:05 LucaGabi

Dose this work with netstandard 2.1 ?

LucaGabi avatar May 17 '21 20:05 LucaGabi

@LucaGabi Did you ever figure this out? I made a simple project now with .NET 6.0 to test this, and whereas the dto is generated as expected, the mapper class is empty.

andrerav avatar Feb 24 '22 19:02 andrerav

@LucaGabi After a lot of experimentation I have concluded that the mapper generation does not seem to work properly if the register class and the generated DTO is not in the same assembly. I have not entirely confirmed it yet, but this does indeed seem to be the case. So a quickfix is to place the mapping register class in the same project as the generated DTO files and run mapster tool on that assembly.

andrerav avatar Feb 24 '22 22:02 andrerav

Cleaning files inside Debug (bin/Debug) and obj folders, worked for me and the mappers methods generated.

hassan-gasemi avatar Apr 07 '22 18:04 hassan-gasemi

Another solution is to run the build command twice.

hassan-gasemi avatar Apr 07 '22 18:04 hassan-gasemi

@andrerav As the code indicates here https://github.com/MapsterMapper/Mapster/blob/master/src/Mapster.Tool/Program.cs#L396, the types are scanned from the assembly defined in the -a option, but the generated Dtos may be placed in another assembly as the -o option can point to another location outside the assembly that is used for generating the Dtos, so maybe another option can be added to tool arguments to define the output assembly, and thus the code base must map types from both assemblies.

MahmoudSamir101 avatar Jul 11 '22 20:07 MahmoudSamir101

I have the same issue...

@LucaGabi After a lot of experimentation I have concluded that the mapper generation does not seem to work properly if the register class and the generated DTO is not in the same assembly. I have not entirely confirmed it yet, but this does indeed seem to be the case. So a quickfix is to place the mapping register class in the same project as the generated DTO files and run mapster tool on that assembly.

Dam1ran avatar Jul 22 '22 21:07 Dam1ran

Facing the same issue. If you specify -o with a path that differs from a project where you are generating code, mappers extension methods not getting generated.

<Target Name="Mapster" AfterTargets="AfterBuild">
		<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
		<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o ..\AnotherProject\Models -n AnotherProject.Models" />
		<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a &quot;$(TargetDir)$(ProjectName).dll&quot;" />
		<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a &quot;$(TargetDir)$(ProjectName).dll&quot;" />
	</Target>

eng1n88r avatar Aug 02 '22 20:08 eng1n88r

same issue

cherchyk avatar Dec 20 '22 02:12 cherchyk

Our solution is structured following way:

  • Acme.Domain (referenced by other projects)
  • Acme.ComponentOne
  • ...
  • Acme.WebApi

Since domain layer is agnostic to any DTO, I want mapper to be generated in Acme.WebApi (that's the place where I map from/to domain). (My intention is to get just mappers generated, we already have DTOs (both WebAPI using data annotations, or for mongodb using own specific attributes)

I tried several things:

  1. Use domain project as input
  <!-- Acme.WebApi.csproj -->
  <Target Name="Mapster" AfterTargets="AfterBuild">
    <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
    <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a &quot;$(TargetDir)Acme.Domain.dll&quot;" />
  </Target>
  1. Reference type various ways (struggling to understand from docs what types to use though)
// `MyDomainObject` is in `Acme.Domain` assembly
config.AdaptTo("[name]Dto")
    .ForType<MyDomainObject>();

or using AllTypes

// `MyDomainObject` is in `Acme.Domain` assembly
var domainType = typeof(MyDomainObject);
config.AdaptTo("[name]Dto")
    .ForAllTypesInNamespace(domainType.Assembly, domainType.Namespace!);

... but without any success. Is this a bug or just lack of clear documentation? After all, documentation itself states (at the bottom of the page):

Fluent API: if you don't want to touch your domain classes, or generate DTOs from domain types in different assembly.

wdolek avatar Jan 06 '23 15:01 wdolek

Another solution is to run the build command twice.

Running it twice works. It does require a 2nd run of dotnet build otherwise generates an empty mapper.

linux 6.2.7-arch1-1
dotnet 6.0.407
Mapster.Tool 8.3.0
    <Target Name="MapsterGen1">
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o Dtos -r"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o Mappers"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o Mappers"/>
        <!--        Force Mappers -->
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o Mappers"/>
    </Target>

dotnet msbuild -t:CleanGenerated && dotnet clean && dotnet msbuild -t:MapsterGen1

Unsure for now why the need for extra build and extension run to work?

        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build"/>
        <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a &quot;$(TargetDir)$(ProjectName).dll&quot; -o Models"/>

jorgelaranjo avatar Mar 25 '23 14:03 jorgelaranjo