diff --git a/Compentio.Example.Autofac.App/AutofacModule.cs b/Compentio.Example.Autofac.App/AutofacModule.cs new file mode 100644 index 0000000..6bd6650 --- /dev/null +++ b/Compentio.Example.Autofac.App/AutofacModule.cs @@ -0,0 +1,22 @@ +using Autofac; +using Compentio.Example.Autofac.App.Repository; +using Compentio.Example.Autofac.App.Services; +using Compentio.SourceMapper.DependencyInjection; +using System.Diagnostics.CodeAnalysis; + +namespace Compentio.Example.Autofac.App +{ + /// + /// Module with registration for Autofac + /// + [ExcludeFromCodeCoverage] + public class AutofacModule : Module + { + protected override void Load(ContainerBuilder builder) + { + builder.RegisterType().As().InstancePerDependency(); + builder.RegisterType().As().SingleInstance(); + builder.AddMappers(); + } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Compentio.Example.Autofac.App.csproj b/Compentio.Example.Autofac.App/Compentio.Example.Autofac.App.csproj new file mode 100644 index 0000000..018e10d --- /dev/null +++ b/Compentio.Example.Autofac.App/Compentio.Example.Autofac.App.csproj @@ -0,0 +1,24 @@ + + + + net5.0 + + + + + + + + + + + + + + + + + + + + diff --git a/Compentio.Example.Autofac.App/Controllers/BooksController.cs b/Compentio.Example.Autofac.App/Controllers/BooksController.cs new file mode 100644 index 0000000..ba252dd --- /dev/null +++ b/Compentio.Example.Autofac.App/Controllers/BooksController.cs @@ -0,0 +1,29 @@ +using Compentio.Example.Autofac.App.Entities; +using Compentio.Example.Autofac.App.Services; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Compentio.Example.Autofac.App.Controllers +{ + [ExcludeFromCodeCoverage] + [Route("api/[controller]")] + [ApiController] + public class BooksController : ControllerBase + { + private readonly IBooksService _booksServices; + + public BooksController(IBooksService booksService) + { + _booksServices = booksService; + } + + [HttpGet] + public IEnumerable Get() + { + var books = _booksServices.GetBooks(); + + return books.Result; + } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Entities/AddressDao.cs b/Compentio.Example.Autofac.App/Entities/AddressDao.cs new file mode 100644 index 0000000..c27b230 --- /dev/null +++ b/Compentio.Example.Autofac.App/Entities/AddressDao.cs @@ -0,0 +1,15 @@ +using System; + +namespace Compentio.Example.Autofac.App.Entities +{ + public class AddressDao + { + public Guid Id { get; set; } + public string Country { get; set; } + public string Region { get; set; } + public string City { get; set; } + public string PostCode { get; set; } + public string Street { get; set; } + public string HomeNumber { get; set; } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Entities/AddressDto.cs b/Compentio.Example.Autofac.App/Entities/AddressDto.cs new file mode 100644 index 0000000..a68d630 --- /dev/null +++ b/Compentio.Example.Autofac.App/Entities/AddressDto.cs @@ -0,0 +1,15 @@ +using System; + +namespace Compentio.Example.Autofac.App.Entities +{ + public class AddressDto + { + public Guid AddressId { get; set; } + public string Country { get; set; } + public string Region { get; set; } + public string City { get; set; } + public string PostalCode { get; set; } + public string Street { get; set; } + public string Home { get; set; } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Entities/BookDao.cs b/Compentio.Example.Autofac.App/Entities/BookDao.cs new file mode 100644 index 0000000..59c7c06 --- /dev/null +++ b/Compentio.Example.Autofac.App/Entities/BookDao.cs @@ -0,0 +1,14 @@ +using System; + +namespace Compentio.Example.Autofac.App.Entities +{ + public class BookDao + { + public Guid Id { get; set; } + public string Author { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public int PublishingYear { get; set; } + public AddressDao LibraryAddress { get; set; } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Entities/BookDto.cs b/Compentio.Example.Autofac.App/Entities/BookDto.cs new file mode 100644 index 0000000..f1cd50d --- /dev/null +++ b/Compentio.Example.Autofac.App/Entities/BookDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace Compentio.Example.Autofac.App.Entities +{ + public class BookDto + { + public Guid BookId { get; set; } + public string Author { get; set; } + public string Title { get; set; } + public string BookDescription { get; set; } + public int PublishingYear { get; set; } + public AddressDto LibraryAddress { get; set; } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Mapper/IBooksMapper.cs b/Compentio.Example.Autofac.App/Mapper/IBooksMapper.cs new file mode 100644 index 0000000..90fa91e --- /dev/null +++ b/Compentio.Example.Autofac.App/Mapper/IBooksMapper.cs @@ -0,0 +1,27 @@ +using Compentio.Example.Autofac.App.Entities; +using Compentio.SourceMapper.Attributes; + +namespace Compentio.Example.Autofac.App.Mapper +{ + [Mapper] + public interface IBooksMapper + { + [Mapping(Source = nameof(BookDao.Description), Target = nameof(BookDto.BookDescription))] + [Mapping(Source = nameof(BookDao.Id), Target = nameof(BookDto.BookId))] + BookDto MapBookToDto(BookDao source); + + [Mapping(Source = nameof(BookDto.BookDescription), Target = nameof(BookDao.Description))] + [Mapping(Source = nameof(BookDto.BookId), Target = nameof(BookDao.Id))] + BookDao MapBookToDao(BookDto source); + + [Mapping(Source = nameof(AddressDao.PostCode), Target = nameof(AddressDto.PostalCode))] + [Mapping(Source = nameof(AddressDao.HomeNumber), Target = nameof(AddressDto.Home))] + [Mapping(Source = nameof(AddressDao.Id), Target = nameof(AddressDto.AddressId))] + AddressDto MapAddressToDto(AddressDao source); + + [Mapping(Source = nameof(AddressDto.PostalCode), Target = nameof(AddressDao.PostCode))] + [Mapping(Source = nameof(AddressDto.Home), Target = nameof(AddressDao.HomeNumber))] + [Mapping(Source = nameof(AddressDto.AddressId), Target = nameof(AddressDao.Id))] + AddressDao MapAddressToDao(AddressDto source); + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Program.cs b/Compentio.Example.Autofac.App/Program.cs new file mode 100644 index 0000000..dadb072 --- /dev/null +++ b/Compentio.Example.Autofac.App/Program.cs @@ -0,0 +1,31 @@ +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using System.Diagnostics.CodeAnalysis; + +namespace Compentio.Example.Autofac.App +{ + /// + /// Sample code with Autofac Dependency Injection + /// + [ExcludeFromCodeCoverage] + static class Program + { + static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + /// + /// The UseServiceProviderFactory call attaches the + /// Autofac provider to the generic hosting mechanism. + /// + static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .UseServiceProviderFactory(new AutofacServiceProviderFactory()) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Properties/launchSettings.json b/Compentio.Example.Autofac.App/Properties/launchSettings.json new file mode 100644 index 0000000..baaaf65 --- /dev/null +++ b/Compentio.Example.Autofac.App/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:27231", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/books", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Compentio.Example.Autofac.App": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "launchUrl": "api/books", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Compentio.Example.Autofac.App/Repository/BooksRepository.cs b/Compentio.Example.Autofac.App/Repository/BooksRepository.cs new file mode 100644 index 0000000..8126746 --- /dev/null +++ b/Compentio.Example.Autofac.App/Repository/BooksRepository.cs @@ -0,0 +1,43 @@ +using Compentio.Example.Autofac.App.Entities; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Compentio.Example.Autofac.App.Repository +{ + [ExcludeFromCodeCoverage] + public class BooksRepository : IBooksRepository + { + public async Task CreateBook(BookDao book) + { + return await Task.FromResult(_bookDao); + } + + public async Task GetBook(Guid bookId) + { + return await Task.FromResult(_bookDao); + } + + public async Task> GetBooks() + { + var booksList = new List(); + booksList.Add(_bookDao); + + return await Task.FromResult(booksList); + } + + public async Task UpdateBook(BookDao book) + { + return await Task.FromResult(_bookDao); + } + + private readonly BookDao _bookDao = new BookDao() + { + Id = Guid.NewGuid(), + Author = "Lem, S", + Title = "Solaris", + PublishingYear = 1961 + }; + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Repository/IBooksRepository.cs b/Compentio.Example.Autofac.App/Repository/IBooksRepository.cs new file mode 100644 index 0000000..971db1a --- /dev/null +++ b/Compentio.Example.Autofac.App/Repository/IBooksRepository.cs @@ -0,0 +1,18 @@ +using Compentio.Example.Autofac.App.Entities; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Compentio.Example.Autofac.App.Repository +{ + public interface IBooksRepository + { + Task> GetBooks(); + + Task GetBook(Guid bookId); + + Task CreateBook(BookDao book); + + Task UpdateBook(BookDao book); + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Services/BooksService.cs b/Compentio.Example.Autofac.App/Services/BooksService.cs new file mode 100644 index 0000000..d854565 --- /dev/null +++ b/Compentio.Example.Autofac.App/Services/BooksService.cs @@ -0,0 +1,50 @@ +using Compentio.Example.Autofac.App.Entities; +using Compentio.Example.Autofac.App.Mapper; +using Compentio.Example.Autofac.App.Repository; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Threading.Tasks; + +namespace Compentio.Example.Autofac.App.Services +{ + [ExcludeFromCodeCoverage] + public class BooksService : IBooksService + { + private readonly IBooksRepository _booksRepository; + private readonly IBooksMapper _booksMapper; + + public BooksService(IBooksRepository booksRepository, IBooksMapper booksMapper) + { + _booksRepository = booksRepository; + _booksMapper = booksMapper; + } + + public async Task CreateBook(BookDto book) + { + var bookDao = _booksMapper.MapBookToDao(book); + var bookResult = await _booksRepository.CreateBook(bookDao); + return _booksMapper.MapBookToDto(bookResult); + } + + public async Task GetBook(Guid bookId) + { + var bookResult = await _booksRepository.GetBook(bookId); + return _booksMapper.MapBookToDto(bookResult); + } + + public async Task> GetBooks() + { + var booksResult = await _booksRepository.GetBooks(); + return booksResult.Select(bookDao => _booksMapper.MapBookToDto(bookDao)); + } + + public async Task UpdateBook(BookDto book) + { + var bookDao = _booksMapper.MapBookToDao(book); + var updateResult = await _booksRepository.UpdateBook(bookDao); + return _booksMapper.MapBookToDto(updateResult); + } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Services/IBooksService.cs b/Compentio.Example.Autofac.App/Services/IBooksService.cs new file mode 100644 index 0000000..0c56d8b --- /dev/null +++ b/Compentio.Example.Autofac.App/Services/IBooksService.cs @@ -0,0 +1,18 @@ +using Compentio.Example.Autofac.App.Entities; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Compentio.Example.Autofac.App.Services +{ + public interface IBooksService + { + Task> GetBooks(); + + Task GetBook(Guid bookId); + + Task CreateBook(BookDto book); + + Task UpdateBook(BookDto book); + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/Startup.cs b/Compentio.Example.Autofac.App/Startup.cs new file mode 100644 index 0000000..5f4b6ca --- /dev/null +++ b/Compentio.Example.Autofac.App/Startup.cs @@ -0,0 +1,58 @@ +using Autofac; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System.Diagnostics.CodeAnalysis; + +namespace Compentio.Example.Autofac.App +{ + [ExcludeFromCodeCoverage] + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + /// + /// This method gets called by the runtime. Use this method to add services to the container. + /// + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + } + + /// + /// Registration directly with Autofac. This runs after ConfigureServices so the things + /// here will override registrations made in ConfigureServices. + /// + public void ConfigureContainer(ContainerBuilder builder) + { + builder.RegisterModule(new AutofacModule()); + } + + /// + /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + /// + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} \ No newline at end of file diff --git a/Compentio.Example.Autofac.App/appsettings.Development.json b/Compentio.Example.Autofac.App/appsettings.Development.json new file mode 100644 index 0000000..8983e0f --- /dev/null +++ b/Compentio.Example.Autofac.App/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/Compentio.Example.Autofac.App/appsettings.json b/Compentio.Example.Autofac.App/appsettings.json new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ b/Compentio.Example.Autofac.App/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/Compentio.Example.App/Compentio.Example.App.csproj b/Compentio.Example.DotNetCore.App/Compentio.Example.DotNetCore.App.csproj similarity index 63% rename from Compentio.Example.App/Compentio.Example.App.csproj rename to Compentio.Example.DotNetCore.App/Compentio.Example.DotNetCore.App.csproj index d9f9266..4ad346d 100644 --- a/Compentio.Example.App/Compentio.Example.App.csproj +++ b/Compentio.Example.DotNetCore.App/Compentio.Example.DotNetCore.App.csproj @@ -6,11 +6,20 @@ - + + + + + + + + + + diff --git a/Compentio.Example.App/Entities/NoteDao.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDao.cs similarity index 90% rename from Compentio.Example.App/Entities/NoteDao.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDao.cs index ecbc5dd..87fbd32 100644 --- a/Compentio.Example.App/Entities/NoteDao.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDao.cs @@ -1,6 +1,6 @@ using System; -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDao { diff --git a/Compentio.Example.App/Entities/NoteDocumentDao.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentDao.cs similarity index 84% rename from Compentio.Example.App/Entities/NoteDocumentDao.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDocumentDao.cs index 7f79ed8..40d6666 100644 --- a/Compentio.Example.App/Entities/NoteDocumentDao.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentDao.cs @@ -1,4 +1,4 @@ -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDocumentDao { diff --git a/Compentio.Example.App/Entities/NoteDocumentDto.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentDto.cs similarity index 85% rename from Compentio.Example.App/Entities/NoteDocumentDto.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDocumentDto.cs index 09f7da3..715ffef 100644 --- a/Compentio.Example.App/Entities/NoteDocumentDto.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentDto.cs @@ -1,4 +1,4 @@ -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDocumentDto { diff --git a/Compentio.Example.App/Entities/NoteDocumentMetadataDao.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDao.cs similarity index 82% rename from Compentio.Example.App/Entities/NoteDocumentMetadataDao.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDao.cs index fc96dc8..8ace7a0 100644 --- a/Compentio.Example.App/Entities/NoteDocumentMetadataDao.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDao.cs @@ -1,4 +1,4 @@ -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDocumentMetadataDao { diff --git a/Compentio.Example.App/Entities/NoteDocumentMetadataDto.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDto.cs similarity index 82% rename from Compentio.Example.App/Entities/NoteDocumentMetadataDto.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDto.cs index 8382fdc..5ee1349 100644 --- a/Compentio.Example.App/Entities/NoteDocumentMetadataDto.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDocumentMetadataDto.cs @@ -1,4 +1,4 @@ -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDocumentMetadataDto { diff --git a/Compentio.Example.App/Entities/NoteDto.cs b/Compentio.Example.DotNetCore.App/Entities/NoteDto.cs similarity index 80% rename from Compentio.Example.App/Entities/NoteDto.cs rename to Compentio.Example.DotNetCore.App/Entities/NoteDto.cs index 5654a4e..884f398 100644 --- a/Compentio.Example.App/Entities/NoteDto.cs +++ b/Compentio.Example.DotNetCore.App/Entities/NoteDto.cs @@ -1,4 +1,4 @@ -namespace Compentio.Example.App.Entities +namespace Compentio.Example.DotNetCore.App.Entities { public class NoteDto { diff --git a/Compentio.Example.App/Mappers/INotesMapper.cs b/Compentio.Example.DotNetCore.App/Mappers/INotesMapper.cs similarity index 86% rename from Compentio.Example.App/Mappers/INotesMapper.cs rename to Compentio.Example.DotNetCore.App/Mappers/INotesMapper.cs index 6cde041..7487ce6 100644 --- a/Compentio.Example.App/Mappers/INotesMapper.cs +++ b/Compentio.Example.DotNetCore.App/Mappers/INotesMapper.cs @@ -1,8 +1,8 @@ -using Compentio.Example.App.Entities; +using Compentio.Example.DotNetCore.App.Entities; using Compentio.SourceMapper.Attributes; using System; -namespace Compentio.Example.App.Mappers +namespace Compentio.Example.DotNetCore.App.Mappers { [Mapper] public interface INotesMapper diff --git a/Compentio.Example.App/Mappers/NotesClassMapper.cs b/Compentio.Example.DotNetCore.App/Mappers/NotesClassMapper.cs similarity index 81% rename from Compentio.Example.App/Mappers/NotesClassMapper.cs rename to Compentio.Example.DotNetCore.App/Mappers/NotesClassMapper.cs index be0d053..d0175ce 100644 --- a/Compentio.Example.App/Mappers/NotesClassMapper.cs +++ b/Compentio.Example.DotNetCore.App/Mappers/NotesClassMapper.cs @@ -1,9 +1,11 @@ -using Compentio.Example.App.Entities; +using Compentio.Example.DotNetCore.App.Entities; using Compentio.SourceMapper.Attributes; using System; +using System.Diagnostics.CodeAnalysis; -namespace Compentio.Example.App.Mappers +namespace Compentio.Example.DotNetCore.App.Mappers { + [ExcludeFromCodeCoverage] [Mapper(ClassName = "NotesMappings")] public abstract class NotesClassMapper { diff --git a/Compentio.Example.App/Program.cs b/Compentio.Example.DotNetCore.App/Program.cs similarity index 78% rename from Compentio.Example.App/Program.cs rename to Compentio.Example.DotNetCore.App/Program.cs index 2ad4f18..bee9baf 100644 --- a/Compentio.Example.App/Program.cs +++ b/Compentio.Example.DotNetCore.App/Program.cs @@ -1,15 +1,20 @@ -using Compentio.Example.App.Repositories; -using Compentio.Example.App.Services; +using Compentio.Example.DotNetCore.App.Repositories; +using Compentio.Example.DotNetCore.App.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.Linq; using System.Threading.Tasks; using Compentio.SourceMapper.DependencyInjection; +using System.Diagnostics.CodeAnalysis; namespace Compentio.ConsoleApp { - class Program + /// + /// Sample code using standard DotNetCore Dependency Injection + /// + [ExcludeFromCodeCoverage] + static class Program { static async Task Main(string[] args) { diff --git a/Compentio.Example.App/Repositories/NotesRepository.cs b/Compentio.Example.DotNetCore.App/Repositories/NotesRepository.cs similarity index 88% rename from Compentio.Example.App/Repositories/NotesRepository.cs rename to Compentio.Example.DotNetCore.App/Repositories/NotesRepository.cs index 9fc5977..0d90038 100644 --- a/Compentio.Example.App/Repositories/NotesRepository.cs +++ b/Compentio.Example.DotNetCore.App/Repositories/NotesRepository.cs @@ -1,9 +1,10 @@ -using Compentio.Example.App.Entities; +using Compentio.Example.DotNetCore.App.Entities; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; -namespace Compentio.Example.App.Repositories +namespace Compentio.Example.DotNetCore.App.Repositories { public interface INotesRepository { @@ -13,6 +14,7 @@ public interface INotesRepository Task UpdateNote(NoteDao note); } + [ExcludeFromCodeCoverage] public class NotesRepository : INotesRepository { public async Task CreateNote(NoteDao note) diff --git a/Compentio.Example.App/Services/NotesService.cs b/Compentio.Example.DotNetCore.App/Services/NotesService.cs similarity index 84% rename from Compentio.Example.App/Services/NotesService.cs rename to Compentio.Example.DotNetCore.App/Services/NotesService.cs index 7f8918e..a14aded 100644 --- a/Compentio.Example.App/Services/NotesService.cs +++ b/Compentio.Example.DotNetCore.App/Services/NotesService.cs @@ -1,13 +1,14 @@ -using Compentio.Example.App.Entities; -using Compentio.Example.App.Mappers; -using Compentio.Example.App.Repositories; +using Compentio.Example.DotNetCore.App.Entities; +using Compentio.Example.DotNetCore.App.Mappers; +using Compentio.Example.DotNetCore.App.Repositories; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Compentio.Example.App.Services +namespace Compentio.Example.DotNetCore.App.Services { public interface INotesService { @@ -17,6 +18,7 @@ public interface INotesService Task UpdateNote(NoteDto note); } + [ExcludeFromCodeCoverage] public class NotesService : INotesService { private readonly INotesRepository _repository; diff --git a/Compentio.SourceMapper.Generator/Compentio.SourceMapper.csproj b/Compentio.SourceMapper.Generator/Compentio.SourceMapper.csproj index c31618e..e894b14 100644 --- a/Compentio.SourceMapper.Generator/Compentio.SourceMapper.csproj +++ b/Compentio.SourceMapper.Generator/Compentio.SourceMapper.csproj @@ -9,11 +9,11 @@ SourceMapper Aleksander Parchomenko https://alekshura.github.io/SourceMapper/ - 1.0.11.0 - 1.0.11.0 + 1.0.12.0 + 1.0.12.0 Compentio.SourceMapper true - 1.0.11 + 1.0.12 Code generator for mappings based on attributes defined in interfaces or abstrat classes. It is based on .NetCore Source Generators engine and generates classes for mappers during build time of you project. Copyright (c) @alekshura Compentio 2021 https://github.com/alekshura/SourceMapper @@ -51,4 +51,19 @@ + + + True + True + AppStrings.resx + + + + + + ResXFileCodeGenerator + AppStrings.Designer.cs + + + diff --git a/Compentio.SourceMapper.Generator/Diagnostics/DiagnosticsInfo.cs b/Compentio.SourceMapper.Generator/Diagnostics/DiagnosticsInfo.cs index 94146e8..5e6aaaf 100644 --- a/Compentio.SourceMapper.Generator/Diagnostics/DiagnosticsInfo.cs +++ b/Compentio.SourceMapper.Generator/Diagnostics/DiagnosticsInfo.cs @@ -21,7 +21,7 @@ internal class DiagnosticsInfo /// /// Exception thrown during code generation /// - internal Exception? Exception { get; set; } + internal virtual Exception? Exception { get; set; } /// /// Formatted message that is shoun in build console /// diff --git a/Compentio.SourceMapper.Generator/Generators/MainSourceGenerator.cs b/Compentio.SourceMapper.Generator/Generators/MainSourceGenerator.cs index 765e8aa..a536245 100644 --- a/Compentio.SourceMapper.Generator/Generators/MainSourceGenerator.cs +++ b/Compentio.SourceMapper.Generator/Generators/MainSourceGenerator.cs @@ -1,6 +1,7 @@ using Compentio.SourceMapper.Attributes; using Compentio.SourceMapper.Metadata; using Compentio.SourceMapper.Processors.DependencyInjection; +using Compentio.SourceMapper.Resources; using Microsoft.CodeAnalysis; using System; using System.Collections.Generic; @@ -29,7 +30,7 @@ public void Execute(GeneratorExecutionContext context) if (context.SyntaxReceiver is not MappersSyntaxReceiver receiver) return; - var sourcesMetadata = SourcesMetadata.Create(GetDependencyInjectionType(context.Compilation.ReferencedAssemblyNames)); + var sourcesMetadata = SourcesMetadata.Create(DependencyInjectionService.GetDependencyInjectionType(context.Compilation.ReferencedAssemblyNames)); foreach (var typeDeclaration in receiver.Candidates) { @@ -70,25 +71,5 @@ private bool IsMapperType(ITypeSymbol type) return type.GetAttributes() .Any(a => a.AttributeClass?.Name == nameof(MapperAttribute)) && type.IsAbstract; } - - private DependencyInjectionType GetDependencyInjectionType(IEnumerable assemblies) - { - if (assemblies.Any(ai => ai.Name.Equals("Microsoft.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase))) - { - return DependencyInjectionType.DotNetCore; - } - - if (assemblies.Any(ai => ai.Name.Equals("Autofac.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase))) - { - return DependencyInjectionType.Autofac; - } - - if (assemblies.Any(ai => ai.Name.Equals("StructureMap.Microsoft.DependencyInjection", StringComparison.OrdinalIgnoreCase))) - { - return DependencyInjectionType.Autofac; - } - - return DependencyInjectionType.None; - } } } diff --git a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/AutofacProcessorStrategy.cs b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/AutofacProcessorStrategy.cs index b5f657a..03bc524 100644 --- a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/AutofacProcessorStrategy.cs +++ b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/AutofacProcessorStrategy.cs @@ -1,5 +1,8 @@ -using Compentio.SourceMapper.Metadata; +using Compentio.SourceMapper.Diagnostics; +using Compentio.SourceMapper.Metadata; using System; +using System.Collections.Generic; +using System.Text; namespace Compentio.SourceMapper.Processors.DependencyInjection { @@ -7,7 +10,42 @@ internal class AutofacProcessorStrategy : IDependencyInjectionStrategy { public IResult GenerateCode(ISourcesMetadata sourcesMetadata) { - throw new NotImplementedException(); + var result = @$"// + // + + using System; + using Microsoft.Extensions.DependencyInjection; + using Autofac; + using Autofac.Extensions.DependencyInjection; + + { $"namespace Compentio.SourceMapper.DependencyInjection"} + {{ + public static class {sourcesMetadata.DependencyInjection.DependencyInjectionClassName} + {{ + public static ContainerBuilder AddMappers(this ContainerBuilder builder) + {{ + { GenerateBuilder(sourcesMetadata) } + return builder; + }} + }} + }} + "; + + return Result.Ok(result); + } + + private string GenerateBuilder(ISourcesMetadata sourcesMetadata) + { + if (sourcesMetadata.Mappers == null) return string.Empty; + + var builder = new StringBuilder(); + + foreach (var mapper in sourcesMetadata.Mappers) + { + builder.AppendLine($"builder.RegisterType<{mapper.Namespace}.{mapper.TargetClassName}>().As<{mapper.Namespace}.{mapper.Name}>().SingleInstance();"); + } + + return builder.ToString(); } } } diff --git a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjection.cs b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjection.cs index 2bdffa8..2b80155 100644 --- a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjection.cs +++ b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjection.cs @@ -1,8 +1,10 @@ -namespace Compentio.SourceMapper.Processors.DependencyInjection +using Compentio.SourceMapper.Resources; + +namespace Compentio.SourceMapper.Processors.DependencyInjection { internal class DependencyInjection { - internal DependencyInjectionType DependencyInjectionType { get; set; } - internal string DependencyInjectionClassName { get; } = "MappersDependencyInjectionExtensions"; + internal virtual DependencyInjectionType DependencyInjectionType { get; set; } + internal string DependencyInjectionClassName { get; } = AppStrings.DependencyInjectionClassName; } } \ No newline at end of file diff --git a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjectionService.cs b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjectionService.cs new file mode 100644 index 0000000..90b2790 --- /dev/null +++ b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/DependencyInjectionService.cs @@ -0,0 +1,43 @@ +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Compentio.SourceMapper.Processors.DependencyInjection +{ + /// + /// Services methods for DependencyInjection class + /// + internal static class DependencyInjectionService + { + private const string AutofacAssemblyName = "Autofac.Extensions.DependencyInjection"; + private const string DotNetCoreAssemblyName = "Microsoft.Extensions.DependencyInjection"; + private const string StructureMapAssemblyName = "StructureMap.Microsoft.DependencyInjection"; + + /// + /// Return dependency injection container type based on assembies collection + /// + /// Collection of assemblies + /// + internal static DependencyInjectionType GetDependencyInjectionType(IEnumerable assemblies) + { + if (assemblies.Any(ai => ai.Name.Equals(AutofacAssemblyName, StringComparison.OrdinalIgnoreCase))) + { + return DependencyInjectionType.Autofac; + } + + if (assemblies.Any(ai => ai.Name.Equals(DotNetCoreAssemblyName, StringComparison.OrdinalIgnoreCase))) + { + return DependencyInjectionType.DotNetCore; + } + + if (assemblies.Any(ai => ai.Name.Equals(StructureMapAssemblyName, StringComparison.OrdinalIgnoreCase))) + { + return DependencyInjectionType.StructureMap; + } + + return DependencyInjectionType.None; + } + } +} diff --git a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/ProcessorStrategyFactory.cs b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/ProcessorStrategyFactory.cs index f91f624..46bc2d9 100644 --- a/Compentio.SourceMapper.Generator/Processors/DependencyInjection/ProcessorStrategyFactory.cs +++ b/Compentio.SourceMapper.Generator/Processors/DependencyInjection/ProcessorStrategyFactory.cs @@ -5,19 +5,20 @@ namespace Compentio.SourceMapper.Processors.DependencyInjection { internal static class DependencyInjectionStrategyFactory { - private readonly static Dictionary _dependencyInjectionStrategies = new() + internal readonly static Dictionary DependencyInjectionStrategies = new() { - { DependencyInjectionType.DotNetCore, new DotnetCoreProcessorStrategy() } + { DependencyInjectionType.DotNetCore, new DotnetCoreProcessorStrategy() }, + { DependencyInjectionType.Autofac, new AutofacProcessorStrategy() } }; internal static IDependencyInjectionStrategy? GetStrategy(ISourcesMetadata sourcesMetadata) { - if (!_dependencyInjectionStrategies.ContainsKey(sourcesMetadata.DependencyInjection.DependencyInjectionType)) + if (!DependencyInjectionStrategies.ContainsKey(sourcesMetadata.DependencyInjection.DependencyInjectionType)) { return null; } - return _dependencyInjectionStrategies[sourcesMetadata.DependencyInjection.DependencyInjectionType]; + return DependencyInjectionStrategies[sourcesMetadata.DependencyInjection.DependencyInjectionType]; } } diff --git a/Compentio.SourceMapper.Generator/Processors/Result.cs b/Compentio.SourceMapper.Generator/Processors/Result.cs index fc86306..ba2c2f2 100644 --- a/Compentio.SourceMapper.Generator/Processors/Result.cs +++ b/Compentio.SourceMapper.Generator/Processors/Result.cs @@ -76,7 +76,7 @@ internal static IResult Error(Exception exception) public IEnumerable? Diagnostics => _diagnostics; - public bool IsSuccess => !_diagnostics.Any(info => info.Exception is not null); + public bool IsSuccess => _diagnostics is null || !_diagnostics.Any(info => info.Exception is not null); private string FormatCode(string code) { diff --git a/Compentio.SourceMapper.Generator/Resources/AppStrings.Designer.cs b/Compentio.SourceMapper.Generator/Resources/AppStrings.Designer.cs new file mode 100644 index 0000000..9969b68 --- /dev/null +++ b/Compentio.SourceMapper.Generator/Resources/AppStrings.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Compentio.SourceMapper.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class AppStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AppStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Compentio.SourceMapper.Resources.AppStrings", typeof(AppStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to MappersDependencyInjectionExtensions. + /// + internal static string DependencyInjectionClassName { + get { + return ResourceManager.GetString("DependencyInjectionClassName", resourceCulture); + } + } + } +} diff --git a/Compentio.SourceMapper.Generator/Resources/AppStrings.resx b/Compentio.SourceMapper.Generator/Resources/AppStrings.resx new file mode 100644 index 0000000..f4f1847 --- /dev/null +++ b/Compentio.SourceMapper.Generator/Resources/AppStrings.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + MappersDependencyInjectionExtensions + + \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/DependencyInjections/AutofacProcessorStrategyTests.cs b/Compentio.SourceMapper.Tests/DependencyInjections/AutofacProcessorStrategyTests.cs new file mode 100644 index 0000000..bb70f2f --- /dev/null +++ b/Compentio.SourceMapper.Tests/DependencyInjections/AutofacProcessorStrategyTests.cs @@ -0,0 +1,74 @@ +using AutoFixture; +using Compentio.SourceMapper.Metadata; +using Compentio.SourceMapper.Processors.DependencyInjection; +using FluentAssertions; +using Moq; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Xunit; + +namespace Compentio.SourceMapper.Tests.DependencyInjections +{ + public class AutofacProcessorStrategyTests + { + private readonly IFixture _fixture; + private readonly Mock _mockSourceMetadata; + private const string BuilderRegisterService = "builder.RegisterType"; + + public AutofacProcessorStrategyTests() + { + _fixture = new Fixture(); + _mockSourceMetadata = _fixture.Create>(); + _mockSourceMetadata.Setup(m => m.DependencyInjection).Returns(new DependencyInjection() { DependencyInjectionType = DependencyInjectionType.Autofac }); + } + + [Fact] + public void GenerateCode_WithoutMappers_ReturnProperResult() + { + // Arrange + _mockSourceMetadata.Setup(m => m.Mappers).Returns((IReadOnlyCollection)null); + + // Act + var autofacProcessorStrategy = new AutofacProcessorStrategy(); + var result = autofacProcessorStrategy.GenerateCode(_mockSourceMetadata.Object); + + // Assert + result.Should().NotBeNull(); + result.IsSuccess.Should().BeTrue(); + } + + [Fact] + public void GenerateCode_WithoutMappers_NotRegisterAnyService() + { + // Arrange + _mockSourceMetadata.Setup(m => m.Mappers).Returns((IReadOnlyCollection)null); + + // Act + var autofacProcessorStrategy = new AutofacProcessorStrategy(); + var result = autofacProcessorStrategy.GenerateCode(_mockSourceMetadata.Object); + + // Assert + result.GeneratedCode.Should().NotContain(BuilderRegisterService); + } + + [Fact] + public void GenerateCode_WithMapper_RegisterService() + { + // Arrange + var mockMapperMetadata = _fixture.Create>(); + + mockMapperMetadata.Setup(m => m.Name).Returns("Name"); + mockMapperMetadata.Setup(m => m.Namespace).Returns("Namespace"); + mockMapperMetadata.Setup(m => m.TargetClassName).Returns("TargetClassName"); + + _mockSourceMetadata.Setup(s => s.Mappers).Returns(new ReadOnlyCollection(new List { mockMapperMetadata.Object })); + + // Act + var autofacProcessorStrategy = new AutofacProcessorStrategy(); + var result = autofacProcessorStrategy.GenerateCode(_mockSourceMetadata.Object); + + // Assert + result.GeneratedCode.Should().Contain(BuilderRegisterService); + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionServiceTests.cs b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionServiceTests.cs new file mode 100644 index 0000000..9f79b60 --- /dev/null +++ b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionServiceTests.cs @@ -0,0 +1,67 @@ +using Compentio.SourceMapper.Processors.DependencyInjection; +using FluentAssertions; +using Microsoft.CodeAnalysis; +using System.Collections.Generic; +using Xunit; + +namespace Compentio.SourceMapper.Tests.DependencyInjections +{ + public class DependencyInjectionServiceTests + { + [Fact] + public void GetType_DotNetCoreAssembly_ReturnDotNetCoreType() + { + // Arrange + var fakeAssembly = new FakeAssembly("Microsoft.Extensions.DependencyInjection"); + var assemblyCollection = new List { AssemblyIdentity.FromAssemblyDefinition(fakeAssembly) }; + + // Act + var result = DependencyInjectionService.GetDependencyInjectionType(assemblyCollection); + + // Assert + result.Should().Be(DependencyInjectionType.DotNetCore); + } + + [Fact] + public void GetType_AutofacAssembly_ReturnAutofacType() + { + // Arrange + var fakeAssembly = new FakeAssembly("Autofac.Extensions.DependencyInjection"); + var assemblyCollection = new List { AssemblyIdentity.FromAssemblyDefinition(fakeAssembly) }; + + // Act + var result = DependencyInjectionService.GetDependencyInjectionType(assemblyCollection); + + // Assert + result.Should().Be(DependencyInjectionType.Autofac); + } + + [Fact] + public void GetType_StructureMapAssembly_ReturnStructureMapType() + { + // Arrange + var fakeAssembly = new FakeAssembly("StructureMap.Microsoft.DependencyInjection"); + var assemblyCollection = new List { AssemblyIdentity.FromAssemblyDefinition(fakeAssembly) }; + + // Act + var result = DependencyInjectionService.GetDependencyInjectionType(assemblyCollection); + + // Assert + result.Should().Be(DependencyInjectionType.StructureMap); + } + + [Fact] + public void GetType_NoDependencyInjection_ReturnNoneType() + { + // Arrange + var fakeAssembly = new FakeAssembly("NoDependencyInjection"); + var assemblyCollection = new List { AssemblyIdentity.FromAssemblyDefinition(fakeAssembly) }; + + // Act + var result = DependencyInjectionService.GetDependencyInjectionType(assemblyCollection); + + // Assert + result.Should().Be(DependencyInjectionType.None); + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionStrategyFactoryTests.cs b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionStrategyFactoryTests.cs new file mode 100644 index 0000000..e07f240 --- /dev/null +++ b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionStrategyFactoryTests.cs @@ -0,0 +1,95 @@ +using AutoFixture; +using Compentio.SourceMapper.Metadata; +using Compentio.SourceMapper.Processors.DependencyInjection; +using FluentAssertions; +using Moq; +using Xunit; + +namespace Compentio.SourceMapper.Tests.DependencyInjections +{ + public class DependencyInjectionStrategyFactoryTests + { + private readonly IFixture _fixture; + private readonly Mock _mockSourceMetadata; + private readonly Mock _mockDependencyInjection; + + public DependencyInjectionStrategyFactoryTests() + { + _fixture = new Fixture(); + _mockSourceMetadata = _fixture.Create>(); + _mockDependencyInjection = _fixture.Create>(); + } + + [Fact] + public void GetStrategy_WithNoneDependencyInjection_ReturnNull() + { + // Arrange + _mockDependencyInjection.Setup(d => d.DependencyInjectionType).Returns(DependencyInjectionType.None); + _mockSourceMetadata.Setup(m => m.DependencyInjection).Returns(_mockDependencyInjection.Object); + + //Act + var dependencyInjectionStrategy = DependencyInjectionStrategyFactory.GetStrategy(_mockSourceMetadata.Object); + + //Assert + dependencyInjectionStrategy.Should().BeNull(); + } + + [Fact] + public void GetStrategy_ForDotNetCoreType_ReturnDotnetCoreProcessorStrategy() + { + // Arrange + _mockDependencyInjection.Setup(d => d.DependencyInjectionType).Returns(DependencyInjectionType.DotNetCore); + _mockSourceMetadata.Setup(m => m.DependencyInjection).Returns(_mockDependencyInjection.Object); + + //Act + var dependencyInjectionStrategy = DependencyInjectionStrategyFactory.GetStrategy(_mockSourceMetadata.Object); + + //Assert + dependencyInjectionStrategy.Should().BeOfType(); + } + + [Fact] + public void GetStrategy_ForAutofacType_ReturnAutofacProcessorStrategy() + { + // Arrange + _mockDependencyInjection.Setup(d => d.DependencyInjectionType).Returns(DependencyInjectionType.Autofac); + _mockSourceMetadata.Setup(m => m.DependencyInjection).Returns(_mockDependencyInjection.Object); + + //Act + var dependencyInjectionStrategy = DependencyInjectionStrategyFactory.GetStrategy(_mockSourceMetadata.Object); + + //Assert + dependencyInjectionStrategy.Should().BeOfType(); + } + + [Fact] + public void FactoryStrategies_ContainStrategyKey_DotNetCore() + { + // Act + var result = DependencyInjectionStrategyFactory.DependencyInjectionStrategies.ContainsKey(DependencyInjectionType.DotNetCore); + + //Assert + result.Should().BeTrue(); + } + + [Fact] + public void FactoryStrategies_ContainStrategyKey_Autofac() + { + // Act + var result = DependencyInjectionStrategyFactory.DependencyInjectionStrategies.ContainsKey(DependencyInjectionType.Autofac); + + //Assert + result.Should().BeTrue(); + } + + [Fact] + public void FactoryStrategies_NotContainStrategyKey_None() + { + // Act + var result = DependencyInjectionStrategyFactory.DependencyInjectionStrategies.ContainsKey(DependencyInjectionType.None); + + //Assert + result.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionTests.cs b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionTests.cs new file mode 100644 index 0000000..c61d20c --- /dev/null +++ b/Compentio.SourceMapper.Tests/DependencyInjections/DependencyInjectionTests.cs @@ -0,0 +1,30 @@ +using Compentio.SourceMapper.Processors.DependencyInjection; +using FluentAssertions; +using System.Globalization; +using System.Resources; +using Xunit; + +namespace Compentio.SourceMapper.Tests.DependencyInjections +{ + public class DependencyInjectionTests + { + [Fact] + public void DependencyInjectionClassName_ReturnProperString() + { + // Act + var dependencyInjection = new DependencyInjection(); + + // Assert + dependencyInjection.DependencyInjectionClassName.Should().NotBeNullOrEmpty(); + dependencyInjection.DependencyInjectionClassName.Should().BeEquivalentTo(GetDependencyInjectionClassNameString()); + } + + private static string GetDependencyInjectionClassNameString() + { + var resourceManager = new ResourceManager(typeof(Resources.AppStrings)); + string message = resourceManager.GetString("DependencyInjectionClassName", CultureInfo.InvariantCulture); + + return message; + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/DependencyInjections/FakeAssembly.cs b/Compentio.SourceMapper.Tests/DependencyInjections/FakeAssembly.cs new file mode 100644 index 0000000..c642023 --- /dev/null +++ b/Compentio.SourceMapper.Tests/DependencyInjections/FakeAssembly.cs @@ -0,0 +1,19 @@ +using System.Reflection; + +namespace Compentio.SourceMapper.Tests.DependencyInjections +{ + public class FakeAssembly : Assembly + { + private readonly string _assemblyName; + + public FakeAssembly(string assemblyName) + { + _assemblyName = assemblyName; + } + + public override AssemblyName GetName(bool copiedName) + { + return new AssemblyName(_assemblyName); + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.Tests/Processors/ResultTests.cs b/Compentio.SourceMapper.Tests/Processors/ResultTests.cs new file mode 100644 index 0000000..149b24d --- /dev/null +++ b/Compentio.SourceMapper.Tests/Processors/ResultTests.cs @@ -0,0 +1,108 @@ +using AutoFixture; +using Compentio.SourceMapper.Diagnostics; +using Compentio.SourceMapper.Processors; +using FluentAssertions; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Compentio.SourceMapper.Tests.Processors +{ + public class ResultTests + { + private readonly IFixture _fixture; + private readonly Mock _mockDiagnosticsInfo; + private readonly IList _diagnosticsInfoList; + private readonly Mock _mockException; + private const string GeneratedCodeTest = "TestCode"; + + public ResultTests() + { + _fixture = new Fixture(); + _mockDiagnosticsInfo = _fixture.Create>(); + _mockException = _fixture.Create>(); + + _diagnosticsInfoList = new List { _mockDiagnosticsInfo.Object }; + } + + [Fact] + public void ResultOk_NoParms_ReturnSuccess() + { + // Act + var result = Result.Ok(null); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Diagnostics.Should().BeNullOrEmpty(); + } + + [Fact] + public void ResultOk_NoExceptions_ReturnSuccess() + { + // Arrange + _mockDiagnosticsInfo.Setup(d => d.Exception).Returns((Exception)null); + + // Act + var result = Result.Ok(string.Empty, _diagnosticsInfoList); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Diagnostics.Any(d => d.Exception is not null).Should().BeFalse(); + } + + [Fact] + public void ResultOk_WithException_ReturnSuccessFalse() + { + // Arrange + _mockDiagnosticsInfo.Setup(d => d.Exception).Returns(new Exception()); + + // Act + var result = Result.Ok(string.Empty, _diagnosticsInfoList); + + // Assert + result.IsSuccess.Should().BeFalse(); + result.Diagnostics.Any(d => d.Exception is not null).Should().BeTrue(); + } + + [Fact] + public void ResultError_ReportException_ReturnSuccessFalse() + { + // Arrange + _mockDiagnosticsInfo.Setup(d => d.Exception).Returns(new Exception()); + + // Act + var result = Result.Error(_mockException.Object); + + // Assert + result.IsSuccess.Should().BeFalse(); + result.Diagnostics.Any(d => d.Exception is not null).Should().BeTrue(); + } + + [Fact] + public void GeneratedCore_FromResultOk_ReturnCode() + { + //Act + var result = Result.Ok(GeneratedCodeTest); + var code = result.GeneratedCode; + + // Assert + code.Should().NotBeNullOrEmpty(); + } + + [Fact] + public void GeneratedCode_FromResultError_EmptyCode() + { + // Arrange + _mockDiagnosticsInfo.Setup(d => d.Exception).Returns(new Exception()); + + // Act + var result = Result.Error(_mockException.Object); + var code = result.GeneratedCode; + + // Assert + code.Should().BeNullOrEmpty(); + } + } +} \ No newline at end of file diff --git a/Compentio.SourceMapper.sln b/Compentio.SourceMapper.sln index b0e0f50..5bbd7b1 100644 --- a/Compentio.SourceMapper.sln +++ b/Compentio.SourceMapper.sln @@ -5,14 +5,16 @@ VisualStudioVersion = 16.0.31515.178 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compentio.SourceMapper", "Compentio.SourceMapper.Generator\Compentio.SourceMapper.csproj", "{B66B2628-50B5-4AE5-A88A-5DEB39FFB449}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compentio.Example.App", "Compentio.Example.App\Compentio.Example.App.csproj", "{792D18D8-5E2C-4DEC-95C9-44B8F8AF2FAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compentio.Example.DotNetCore.App", "Compentio.Example.DotNetCore.App\Compentio.Example.DotNetCore.App.csproj", "{792D18D8-5E2C-4DEC-95C9-44B8F8AF2FAA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{59821036-CEBB-4E27-88A9-43BF86492019}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compentio.SourceMapper.Tests", "Compentio.SourceMapper.Tests\Compentio.SourceMapper.Tests.csproj", "{6930DDF1-653B-4200-96BA-6C3BB2FEA2B4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compentio.SourceMapper.Tests", "Compentio.SourceMapper.Tests\Compentio.SourceMapper.Tests.csproj", "{6930DDF1-653B-4200-96BA-6C3BB2FEA2B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compentio.Example.Autofac.App", "Compentio.Example.Autofac.App\Compentio.Example.Autofac.App.csproj", "{043B1040-8796-4448-BD00-83C2692716A5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -32,6 +34,10 @@ Global {6930DDF1-653B-4200-96BA-6C3BB2FEA2B4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6930DDF1-653B-4200-96BA-6C3BB2FEA2B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6930DDF1-653B-4200-96BA-6C3BB2FEA2B4}.Release|Any CPU.Build.0 = Release|Any CPU + {043B1040-8796-4448-BD00-83C2692716A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {043B1040-8796-4448-BD00-83C2692716A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {043B1040-8796-4448-BD00-83C2692716A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {043B1040-8796-4448-BD00-83C2692716A5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 43ef6b9..ff5f3a5 100644 --- a/README.md +++ b/README.md @@ -198,8 +198,12 @@ public abstract class UserMapper For more examples see [Wiki examples](https://github.com/alekshura/SourceMapper/wiki/Examples#mapping-collections). ## Dependency injection +The `Compentio.SourceMapper` searches for 3 main dependency container packages (`Microsoft.Extensions.DependencyInjection`, `Autofac.Extensions.DependencyInjection`, and `StructureMap.Microsoft.DependencyInjection`) and generates extension code. If there no any container packages found, Dependency Injection extension class is not generated. + To simplify adding dependency injection for mappers `MappersDependencyInjectionExtensions` class is generated, that can be used (for now only for -`Microsoft.Extensions.DependencyInjection`) by adding `AddMappers()` that adds all mappers defined in the project: +`Microsoft.Extensions.DependencyInjection` and `Autofac.Extensions.DependencyInjection`) by adding `AddMappers()` that adds all mappers defined in the project. + +For `Microsoft.Extensions.DependencyInjection`, in service configuration: ```csharp Host.CreateDefaultBuilder(args) @@ -209,6 +213,37 @@ To simplify adding dependency injection for mappers `MappersDependencyInjectionE // .AddMappers()); ``` -The `Compentio.SourceMapper` searches for 3 main dependency container packages (`Microsoft.Extensions.DependencyInjection`, `Autofac.Extensions.DependencyInjection`, and `StructureMap.Microsoft.DependencyInjection`) and generates extension code. If there no any container packages found, Dependency Injection extension class is not generated. +In case of `Autofac.Extensions.DependencyInjection`, container configuration can be separated in module file `AutofacModules`, where we place registrations directly with Autofac: + +```csharp +public class AutofacModule : Module +{ + protected override void Load(ContainerBuilder builder) + { + builder.RegisterType().As().InstancePerDependency(); + builder.RegisterType().As().SingleInstance(); + builder.AddMappers(); + } +} +``` +That module need to be register in container configure section of `Startup` file: + +```csharp +public void ConfigureContainer(ContainerBuilder builder) +{ + builder.RegisterModule(new AutofacModule()); +} +``` + +To run Autofac mechanism, we need to call Autofac factory with attached `Startup` file by using: + +```csharp +Host.CreateDefaultBuilder(args) + .UseServiceProviderFactory(new AutofacServiceProviderFactory()) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +``` \ No newline at end of file