Mapster
Mapster copied to clipboard
Tool generates empty mapper
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; }
}
Dose this work with netstandard 2.1 ?
@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.
@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.
Cleaning files inside Debug (bin/Debug) and obj folders, worked for me and the mappers methods generated.
Another solution is to run the build command twice.
@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.
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.
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 "$(TargetDir)$(ProjectName).dll" -o ..\AnotherProject\Models -n AnotherProject.Models" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll"" />
</Target>
same issue
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:
- 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 "$(TargetDir)Acme.Domain.dll"" />
</Target>
- 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.
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 "$(TargetDir)$(ProjectName).dll" -o Dtos -r"/>
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll" -o Mappers"/>
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll" -o Mappers"/>
<!-- Force Mappers -->
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build"/>
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll" -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 "$(TargetDir)$(ProjectName).dll" -o Models"/>