Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CompileMapper (TenJames.CompMap)

> CompMap is a C# Roslyn-based source generator that automatically creates mapping methods between classes. It simplifies the process of converting one class type to another by generating the necessary code at compile time.
> CompMap is a C# Roslyn-based source generator that automatically creates mapping methods between classes or records. It simplifies the process of converting one class type to another by generating the necessary code at compile time.

Ensure your DTO's are correctly mapped with compile time safety, to ensure valid changes are tracked in your project.

Expand Down Expand Up @@ -108,7 +108,7 @@ The package will automatically be configured as a source generator. If you need
/>
```

Note: The `OutputItemType="Analyzer"` and `ReferenceOutputAssembly="false"` attributes are typically not required when using `dotnet add package`, as the package is already configured correctly.
Note: The `OutputItemType="Analyzer"` and `ReferenceOutputAssembly="false"` attributes are typically not required when using `dotnet add package`.

### Component registration

Expand All @@ -133,7 +133,7 @@ Add Attributes to your DTO classes and then enjoy the generated mapping methods
## Example


See the [Example](./TenJames.CompMap/TenJames.CompMap.Example) project for a complete working example.
See the [Example](./example/Example.Console) project for a complete working example.


## Contributing
Expand Down
69 changes: 26 additions & 43 deletions TenJames.CompMap.sln
Original file line number Diff line number Diff line change
@@ -1,73 +1,56 @@


Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TenJames.CompMap", "TenJames.CompMap\TenJames.CompMap\TenJames.CompMap.csproj", "{9B224A43-D90A-4D47-8A92-1E02A9BA5658}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TenJames.CompMap.Tests", "TenJames.CompMap\TenJames.CompMap.Tests\TenJames.CompMap.Tests.csproj", "{045DCA29-C2DC-4707-9521-98097B1B2F84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TenJames.CompMap.Example", "TenJames.CompMap\TenJames.CompMap.Example\TenJames.CompMap.Example.csproj", "{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TenJames.CompMap.IntegrationTests", "TenJames.CompMap\TenJames.CompMap.IntegrationTests\TenJames.CompMap.IntegrationTests.csproj", "{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "example", "example", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Entities", "example\Example.Entities\Example.Entities.csproj", "{11111111-1111-1111-1111-111111111111}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.DTOS", "example\Example.DTOS\Example.DTOS.csproj", "{22222222-2222-2222-2222-222222222222}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Console", "example\Example.Console\Example.Console.csproj", "{33333333-3333-3333-3333-333333333333}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|x64.ActiveCfg = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|x64.Build.0 = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|x86.ActiveCfg = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Debug|x86.Build.0 = Debug|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|Any CPU.Build.0 = Release|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|x64.ActiveCfg = Release|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|x64.Build.0 = Release|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|x86.ActiveCfg = Release|Any CPU
{9B224A43-D90A-4D47-8A92-1E02A9BA5658}.Release|x86.Build.0 = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|x64.ActiveCfg = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|x64.Build.0 = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|x86.ActiveCfg = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Debug|x86.Build.0 = Debug|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|Any CPU.Build.0 = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|x64.ActiveCfg = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|x64.Build.0 = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|x86.ActiveCfg = Release|Any CPU
{045DCA29-C2DC-4707-9521-98097B1B2F84}.Release|x86.Build.0 = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|x64.ActiveCfg = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|x64.Build.0 = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|x86.ActiveCfg = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Debug|x86.Build.0 = Debug|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|Any CPU.Build.0 = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|x64.ActiveCfg = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|x64.Build.0 = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|x86.ActiveCfg = Release|Any CPU
{B7BB7EF5-EBA5-45F2-903F-9A0DBCAD0D9C}.Release|x86.Build.0 = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|x64.ActiveCfg = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|x64.Build.0 = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|x86.ActiveCfg = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Debug|x86.Build.0 = Debug|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|Any CPU.Build.0 = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|x64.ActiveCfg = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|x64.Build.0 = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|x86.ActiveCfg = Release|Any CPU
{8CB48D1B-7F2C-40F5-830D-0BC8AE46B07E}.Release|x86.Build.0 = Release|Any CPU
{11111111-1111-1111-1111-111111111111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11111111-1111-1111-1111-111111111111}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11111111-1111-1111-1111-111111111111}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11111111-1111-1111-1111-111111111111}.Release|Any CPU.Build.0 = Release|Any CPU
{22222222-2222-2222-2222-222222222222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22222222-2222-2222-2222-222222222222}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22222222-2222-2222-2222-222222222222}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22222222-2222-2222-2222-222222222222}.Release|Any CPU.Build.0 = Release|Any CPU
{33333333-3333-3333-3333-333333333333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33333333-3333-3333-3333-333333333333}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33333333-3333-3333-3333-333333333333}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33333333-3333-3333-3333-333333333333}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{11111111-1111-1111-1111-111111111111} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
{22222222-2222-2222-2222-222222222222} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
{33333333-3333-3333-3333-333333333333} = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
EndGlobalSection
EndGlobal
112 changes: 0 additions & 112 deletions TenJames.CompMap/TenJames.CompMap.Example/Entitities.cs

This file was deleted.

24 changes: 0 additions & 24 deletions TenJames.CompMap/TenJames.CompMap.Example/Program.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -465,4 +465,96 @@ public void VehicleCreateDto_MapTo_ShouldMapPropertiesFromBaseClass()
// Assert - Unmapped property
Assert.False(vehicle.IsDeleted);
}

[Fact]
public void ContactReadDto_MapFrom_ShouldMapRecordProperties()
{
// Arrange
var contact = new Contact
{
Id = 1,
FirstName = "Alice",
LastName = "Smith",
Email = "alice.smith@example.com",
Phone = "+1234567890"
};

// Act
var dto = ContactReadDto.MapFrom(_mapper, contact);

// Assert - Matching properties
Assert.Equal(contact.Id, dto.Id);
Assert.Equal(contact.FirstName, dto.FirstName);
Assert.Equal(contact.LastName, dto.LastName);
Assert.Equal(contact.Email, dto.Email);
Assert.Equal(contact.Phone, dto.Phone);

// Assert - Unmapped property (computed)
Assert.Equal("Alice Smith", dto.FullName);
}

[Fact]
public void AddressReadDto_MapFrom_ShouldMapAllRecordProperties()
{
// Arrange
var address = new Address
{
Id = 42,
Street = "123 Main St",
City = "New York",
PostalCode = "10001",
Country = "USA"
};

// Act
var dto = AddressReadDto.MapFrom(_mapper, address);

// Assert
Assert.Equal(address.Id, dto.Id);
Assert.Equal(address.Street, dto.Street);
Assert.Equal(address.City, dto.City);
Assert.Equal(address.PostalCode, dto.PostalCode);
Assert.Equal(address.Country, dto.Country);
}

[Fact]
public void NoteCreateDto_MapTo_ShouldCreateNoteRecord()
{
// Arrange
var dto = new NoteCreateDto
{
Title = "Meeting Notes",
Content = "Important discussion about Q1 goals"
};

// Act
var note = _mapper.Map<Note>(dto);

// Assert - Matching properties
Assert.Equal(dto.Title, note.Title);
Assert.Equal(dto.Content, note.Content);

// Assert - Unmapped properties (auto-generated)
Assert.Equal(0, note.Id);
Assert.NotEqual(default(DateTime), note.CreatedAt);
}

[Fact]
public void Record_MapFrom_ClassEntity_ShouldWork()
{
// This tests mapping from a class entity to a record DTO
var contact = new Contact
{
Id = 5,
FirstName = "Bob",
LastName = "Jones",
Email = "bob@example.com",
Phone = "+9876543210"
};

var dto = _mapper.Map<ContactReadDto>(contact);

Assert.Equal(contact.Id, dto.Id);
Assert.Equal("Bob Jones", dto.FullName);
}
}
Loading
Loading