From 86ef9ede985a8b37437c1298daac2a8d4b5a61b3 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Mon, 26 Jul 2021 16:24:30 +0200 Subject: [PATCH] Fix issue #4 (string?) (#15) * #4 * Only replace if required * fix * private readonly IMapper _mapper; * CRLF --- .../IGeneratorExecutionContext.cs | 2 +- src-examples/ProxyInterfaceConsumer/Person.cs | 110 +++--- .../ProxyInterfaceConsumer/Program.cs | 6 +- .../ProxyInterfaceConsumer.csproj | 2 + .../Extensions/SymbolExtensions.cs | 19 +- .../FileGenerators/BaseGenerator.cs | 16 +- .../PartialInterfacesGenerator.cs | 213 ++++++------ .../FileGenerators/ProxyAttributeGenerator.cs | 54 +-- .../FileGenerators/ProxyClassesGenerator.cs | 328 +++++++++--------- 9 files changed, 396 insertions(+), 354 deletions(-) diff --git a/src-examples/ProxyInterfaceConsumer/IGeneratorExecutionContext.cs b/src-examples/ProxyInterfaceConsumer/IGeneratorExecutionContext.cs index 3346a24..06adf82 100644 --- a/src-examples/ProxyInterfaceConsumer/IGeneratorExecutionContext.cs +++ b/src-examples/ProxyInterfaceConsumer/IGeneratorExecutionContext.cs @@ -1,6 +1,6 @@ namespace ProxyInterfaceConsumer { - [ProxyInterfaceGenerator.Proxy(typeof(Microsoft.CodeAnalysis.GeneratorExecutionContext))] + // [ProxyInterfaceGenerator.Proxy(typeof(Microsoft.CodeAnalysis.GeneratorExecutionContext))] public partial interface IGeneratorExecutionContext { } diff --git a/src-examples/ProxyInterfaceConsumer/Person.cs b/src-examples/ProxyInterfaceConsumer/Person.cs index 9f50110..889ee54 100644 --- a/src-examples/ProxyInterfaceConsumer/Person.cs +++ b/src-examples/ProxyInterfaceConsumer/Person.cs @@ -1,47 +1,65 @@ -using System.Collections.Generic; - -namespace ProxyInterfaceConsumer -{ - public class Person - { - private int PrivateId { get; } - public int Id { get; } - - public long? NullableLong { get; } - - public string Name { get; set; } - - public Address Address { get; set; } - - public List
AddressesLIst { get; set; } - - public Dictionary AddressesDict { get; set; } = new Dictionary(); - public Dictionary AddressesDict2 { get; set; } = new Dictionary(); - - public E E { get; set; } - - public IMyInterface MyInterface { get; set; } - - public int Add(string s) - { - return 600; - } - - public Address AddAddress(Address a) - { - AddressesDict.Add($"{AddressesDict.Count}", a); - - return a; - } - - public void Void() - { - } - } - - public enum E - { - V1, - V2 - } +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ProxyInterfaceConsumer +{ + public class Person + { + private int PrivateId { get; } + public int Id { get; } + + public long? NullableLong { get; } + + public string Name { get; set; } + + public string? StringNullable { get; set; } + + public Address Address { get; set; } + + public List
AddressesLIst { get; set; } + + public Dictionary AddressesDict { get; set; } = new Dictionary(); + public Dictionary AddressesDict2 { get; set; } = new Dictionary(); + + public E E { get; set; } + + public IMyInterface MyInterface { get; set; } + + public int Add(string s) + { + return 600; + } + + public Address AddAddress(Address a) + { + AddressesDict.Add($"{AddressesDict.Count}", a); + + return a; + } + + public void Void() + { + } + + public Task Method1Async() + { + return Task.CompletedTask; + } + + public Task Method2Async() + { + return Task.FromResult(1); + } + + public Task Method3Async() + { + return Task.FromResult((string?)""); + } + } + + public enum E + { + V1, + V2 + } } \ No newline at end of file diff --git a/src-examples/ProxyInterfaceConsumer/Program.cs b/src-examples/ProxyInterfaceConsumer/Program.cs index d78ea89..8614279 100644 --- a/src-examples/ProxyInterfaceConsumer/Program.cs +++ b/src-examples/ProxyInterfaceConsumer/Program.cs @@ -45,9 +45,9 @@ namespace ProxyInterfaceConsumer //p.Void(); Console.WriteLine(JsonSerializer.Serialize(p, JsonSerializerOptions)); - GeneratorExecutionContext g = new GeneratorExecutionContext(); - IGeneratorExecutionContext gc = new GeneratorExecutionContextProxy(g); - int y = 9; + //GeneratorExecutionContext g = new GeneratorExecutionContext(); + //IGeneratorExecutionContext gc = new GeneratorExecutionContextProxy(g); + //int y = 9; } } diff --git a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj index e5cab6a..7718314 100644 --- a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj +++ b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj @@ -3,6 +3,8 @@ net5.0 Exe + 9 + enable diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs index 2f522d2..cf6be4d 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs @@ -7,17 +7,7 @@ namespace ProxyInterfaceSourceGenerator.Extensions { public static TypeEnum GetTypeEnum(this IPropertySymbol p) { - if (p.Type.IsValueType || p.Type.ToString() == "string") - { - return TypeEnum.ValueTypeOrString; - } - - if (p.Type.TypeKind == TypeKind.Interface) - { - return TypeEnum.Interface; - } - - return TypeEnum.Complex; + return GetTypeEnum(p.Type); } public static TypeEnum GetTypeEnum(this IParameterSymbol p) @@ -27,7 +17,7 @@ namespace ProxyInterfaceSourceGenerator.Extensions public static TypeEnum GetTypeEnum(this ITypeSymbol ts) { - if (ts.IsValueType || ts.ToString() == "string") + if (ts.IsValueType || ts.IsString()) { return TypeEnum.ValueTypeOrString; } @@ -40,6 +30,11 @@ namespace ProxyInterfaceSourceGenerator.Extensions return TypeEnum.Complex; } + public static bool IsString(this ITypeSymbol ts) + { + return ts.ToString() == "string" || ts.ToString() == "string?"; + } + public static string ToPropertyText(this IPropertySymbol property, string? overrideType = null) { var get = property.GetMethod != null ? "get; " : string.Empty; diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs index 9dc3302..7535dd4 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs @@ -54,9 +54,9 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators // return propertyTypeAsString; //} - protected string GetPropertyType(IPropertySymbol property) + protected string GetPropertyType(IPropertySymbol property, out bool isReplaced) { - return GetReplacedType(property.Type); + return GetReplacedType(property.Type, out isReplaced); //var propertyTypeAsString = property.Type.ToString(); @@ -95,9 +95,9 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators //return propertyTypeAsString; } - protected string GetParameterType(IParameterSymbol property) + protected string GetParameterType(IParameterSymbol property, out bool isReplaced) { - return GetReplacedType(property.Type); + return GetReplacedType(property.Type, out isReplaced); //var propertyTypeAsString = property.Type.ToString(); //var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == propertyTypeAsString); @@ -135,8 +135,10 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators //return propertyTypeAsString; } - protected string GetReplacedType(ITypeSymbol property) + protected string GetReplacedType(ITypeSymbol property, out bool isReplaced) { + isReplaced = false; + var typeSymbolAsString = property.ToString(); var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeSymbolAsString); @@ -147,6 +149,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators _context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName); } + isReplaced = true; return existing.InterfaceName; } @@ -159,6 +162,8 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeArgumentAsString); if (exist is not null) { + isReplaced = true; + if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) { _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); @@ -171,6 +176,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators return propertyTypeAsStringToBeModified; } + return typeSymbolAsString; } diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs index 1aeb029..3df685f 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs @@ -1,106 +1,109 @@ -using System.Collections.Generic; -using System.Text; -using Microsoft.CodeAnalysis; -using ProxyInterfaceSourceGenerator.Enums; -using ProxyInterfaceSourceGenerator.Extensions; -using ProxyInterfaceSourceGenerator.Utils; - -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator - { - public PartialInterfacesGenerator(Context context) : - base(context) - { - } - - public IEnumerable GenerateFiles() - { - foreach (var ci in _context.CandidateInterfaces) - { - yield return GenerateFile(ci.Value.Namespace, ci.Value.InterfaceName, ci.Value.TypeName, ci.Value.ProxyAll); - } - } - - private FileData GenerateFile(string ns, string interfaceName, string typeName, bool proxyAll) - { - var symbol = GetType(typeName); - - var file = new FileData( - $"{interfaceName}.cs", - CreatePartialInterfaceCode(ns, symbol, interfaceName, proxyAll) - ); - - _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = null, FileData = file }); - - return file; - } - - private string CreatePartialInterfaceCode(string ns, INamedTypeSymbol symbol, string interfaceName, bool proxyAll) => $@"using System; - -namespace {ns} -{{ - public partial interface {interfaceName} - {{ -{GenerateProperties(symbol, proxyAll)} - -{GenerateMethods(symbol)} - }} -}}"; - - private string GenerateProperties(INamedTypeSymbol symbol, bool proxyAll) - { - var str = new StringBuilder(); - - // SimpleProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.ValueTypeOrString)) - { - str.AppendLine($" {property.ToPropertyText()}"); - str.AppendLine(); - } - - // InterfaceProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Interface)) - { - str.AppendLine($" {property.ToPropertyText()}"); - str.AppendLine(); - } - - // ComplexProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Complex)) - { - var type = GetPropertyType(property); - str.AppendLine($" {property.ToPropertyText(type)}"); - str.AppendLine(); - } - - return str.ToString(); - } - - private string GenerateMethods(INamedTypeSymbol symbol) - { - var str = new StringBuilder(); - foreach (var method in MemberHelper.GetPublicMethods(symbol)) - { - var methodParameters = new List(); - foreach (var ps in method.Parameters) - { - if (ps.GetTypeEnum() == TypeEnum.Complex) - { - var type = GetParameterType(ps); - methodParameters.Add($"{type} {ps.Name}"); - } - else - { - methodParameters.Add($"{ps.Type} {ps.Name}"); - } - } - - str.AppendLine($" {GetReplacedType(method.ReturnType)} {method.Name}({string.Join(", ", methodParameters)});"); - str.AppendLine(); - } - - return str.ToString(); - } - } +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis; +using ProxyInterfaceSourceGenerator.Enums; +using ProxyInterfaceSourceGenerator.Extensions; +using ProxyInterfaceSourceGenerator.Utils; + +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator + { + public PartialInterfacesGenerator(Context context) : + base(context) + { + } + + public IEnumerable GenerateFiles() + { + foreach (var ci in _context.CandidateInterfaces) + { + yield return GenerateFile(ci.Value.Namespace, ci.Value.InterfaceName, ci.Value.TypeName, ci.Value.ProxyAll); + } + } + + private FileData GenerateFile(string ns, string interfaceName, string typeName, bool proxyAll) + { + var symbol = GetType(typeName); + + var file = new FileData( + $"{interfaceName}.cs", + CreatePartialInterfaceCode(ns, symbol, interfaceName, proxyAll) + ); + + _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = null, FileData = file }); + + return file; + } + + private string CreatePartialInterfaceCode(string ns, INamedTypeSymbol symbol, string interfaceName, bool proxyAll) => $@"using System; + +namespace {ns} +{{ + public partial interface {interfaceName} + {{ +{GenerateProperties(symbol, proxyAll)} + +{GenerateMethods(symbol)} + }} +}}"; + + private string GenerateProperties(INamedTypeSymbol symbol, bool proxyAll) + { + var str = new StringBuilder(); + + foreach (var property in MemberHelper.GetPublicProperties(symbol)) + { + switch (property.GetTypeEnum()) + { + case TypeEnum.ValueTypeOrString: + case TypeEnum.Interface: + str.AppendLine($" {property.ToPropertyText()}"); + str.AppendLine(); + break; + + default: + var type = GetPropertyType(property, out var isReplaced); + if (isReplaced) + { + str.AppendLine($" {property.ToPropertyText(type)}"); + } + else + { + str.AppendLine($" {property.ToPropertyText()}"); + } + str.AppendLine(); + break; + } + } + + return str.ToString(); + } + + private string GenerateMethods(INamedTypeSymbol symbol) + { + var str = new StringBuilder(); + foreach (var method in MemberHelper.GetPublicMethods(symbol)) + { + var methodParameters = new List(); + foreach (var ps in method.Parameters) + { + if (ps.GetTypeEnum() == TypeEnum.Complex) + { + var type = GetParameterType(ps, out _); + methodParameters.Add($"{type} {ps.Name}"); + } + else + { + methodParameters.Add($"{ps.Type} {ps.Name}"); + } + } + + str.AppendLine($" {GetReplacedType(method.ReturnType, out _)} {method.Name}({string.Join(", ", methodParameters)});"); + str.AppendLine(); + } + + return str.ToString(); + } + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs index fd10040..aa8b85b 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs @@ -1,28 +1,28 @@ -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal class ProxyAttributeGenerator : IFileGenerator - { - private const string ClassName = "ProxyAttribute"; - - public FileData GenerateFile() - { - return new FileData($"{ClassName}.cs", $@"using System; - -namespace ProxyInterfaceGenerator -{{ - [AttributeUsage(AttributeTargets.Interface)] - public class {ClassName} : Attribute - {{ - public Type Type {{ get; }} - public bool ProxyAll {{ get; }} - - public {ClassName}(Type type, bool proxyAll = false) - {{ - Type = type; - ProxyAll = proxyAll; - }} - }} -}}"); - } - } +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal class ProxyAttributeGenerator : IFileGenerator + { + private const string ClassName = "ProxyAttribute"; + + public FileData GenerateFile() + { + return new FileData($"{ClassName}.cs", $@"using System; + +namespace ProxyInterfaceGenerator +{{ + [AttributeUsage(AttributeTargets.Interface)] + public class {ClassName} : Attribute + {{ + public Type Type {{ get; }} + public bool ProxyAll {{ get; }} + + public {ClassName}(Type type, bool proxyAll = false) + {{ + Type = type; + ProxyAll = proxyAll; + }} + }} +}}"); + } + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs index 62b53d2..7b16710 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -1,156 +1,174 @@ -using System.Collections.Generic; -using System.Text; -using Microsoft.CodeAnalysis; -using ProxyInterfaceSourceGenerator.Enums; -using ProxyInterfaceSourceGenerator.Extensions; -using ProxyInterfaceSourceGenerator.Utils; - -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator - { - public ProxyClassesGenerator(Context context) : base(context) - { - } - - public IEnumerable GenerateFiles() - { - foreach (var ci in _context.CandidateInterfaces) - { - yield return GenerateFile(ci.Value.Namespace, ci.Value.InterfaceName, ci.Value.ClassName, ci.Value.TypeName, ci.Value.ProxyAll); - } - } - - private FileData GenerateFile(string ns, string interfaceName, string className, string typeName, bool proxyAll) - { - var symbol = GetType(typeName); - - var file = new FileData( - $"{className}Proxy.cs", - CreateProxyClassCode(ns, symbol, interfaceName, className, proxyAll) - ); - - _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = className, FileData = file }); - - return file; - } - - private string CreateProxyClassCode(string ns, INamedTypeSymbol symbol, string interfaceName, string className, bool proxyAll) => $@"using System; -using AutoMapper; - -namespace {ns} -{{ - public class {className}Proxy : {interfaceName} - {{ - private readonly IMapper? _mapper; - - public {symbol} _Instance {{ get; }} - -{GeneratePublicProperties(symbol, proxyAll)} - -{GeneratePublicMethods(symbol)} - - public {className}Proxy({symbol} instance) - {{ - _Instance = instance; - -{GenerateAutoMapper()} - }} - }} -}}"; - - private string GenerateAutoMapper() - { - if (_context.ReplacedTypes.Count == 0) - { - return string.Empty; - } - - var str = new StringBuilder(); - - str.AppendLine(" _mapper = new MapperConfiguration(cfg =>"); - str.AppendLine(" {"); - foreach (var replacedType in _context.ReplacedTypes) - { - str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();"); - str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();"); - } - str.AppendLine(" }).CreateMapper();"); - - return str.ToString(); - } - - private string GeneratePublicProperties(INamedTypeSymbol symbol, bool proxyAll) - { - var str = new StringBuilder(); - - // SimpleProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.ValueTypeOrString)) - { - str.AppendLine($" public {property.ToPropertyTextForClass()}"); - str.AppendLine(); - } - - // InterfaceProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Interface)) - { - str.AppendLine($" public {property.ToPropertyTextForClass()}"); - str.AppendLine(); - } - - // ComplexProperties - foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Complex)) - { - var type = GetPropertyType(property); - str.AppendLine($" public {property.ToPropertyTextForClass(type)}"); - str.AppendLine(); - } - - return str.ToString(); - } - - private string GeneratePublicMethods(INamedTypeSymbol symbol) - { - var str = new StringBuilder(); - foreach (var method in MemberHelper.GetPublicMethods(symbol)) - { - var methodParameters = new List(); - var invokeParameters = new List(); - - foreach (var ps in method.Parameters) - { - if (ps.GetTypeEnum() == TypeEnum.Complex) - { - methodParameters.Add($"{GetParameterType(ps)} {ps.Name}"); - - invokeParameters.Add($"_mapper.Map<{ps.Type}>({ps.Name})"); - } - else - { - methodParameters.Add($"{ps.Type} {ps.Name}"); - - invokeParameters.Add($"{ps.Name}"); - } - } - - string returnTypeAsString; - string call; - if (method.ReturnType.GetTypeEnum() == TypeEnum.Complex) - { - returnTypeAsString = GetReplacedType(method.ReturnType); - call = $"_mapper.Map<{returnTypeAsString}>(_Instance.{method.Name}({string.Join(", ", invokeParameters)}))"; - } - else - { - returnTypeAsString = method.ReturnType.ToString(); - call = $"_Instance.{method.Name}({string.Join(", ", invokeParameters)})"; - } - - str.AppendLine($" public {returnTypeAsString} {method.Name}({string.Join(", ", methodParameters)}) => {call};"); - str.AppendLine(); - } - - return str.ToString(); - } - } +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis; +using ProxyInterfaceSourceGenerator.Enums; +using ProxyInterfaceSourceGenerator.Extensions; +using ProxyInterfaceSourceGenerator.Utils; + +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator + { + public ProxyClassesGenerator(Context context) : base(context) + { + } + + public IEnumerable GenerateFiles() + { + foreach (var ci in _context.CandidateInterfaces) + { + yield return GenerateFile(ci.Value.Namespace, ci.Value.InterfaceName, ci.Value.ClassName, ci.Value.TypeName, ci.Value.ProxyAll); + } + } + + private FileData GenerateFile(string ns, string interfaceName, string className, string typeName, bool proxyAll) + { + var symbol = GetType(typeName); + + var file = new FileData( + $"{className}Proxy.cs", + CreateProxyClassCode(ns, symbol, interfaceName, className, proxyAll) + ); + + _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = className, FileData = file }); + + return file; + } + + private string CreateProxyClassCode(string ns, INamedTypeSymbol symbol, string interfaceName, string className, bool proxyAll) => $@"using System; +using AutoMapper; + +namespace {ns} +{{ + public class {className}Proxy : {interfaceName} + {{ + public {symbol} _Instance {{ get; }} + +{GeneratePublicProperties(symbol, proxyAll)} + +{GeneratePublicMethods(symbol)} + + public {className}Proxy({symbol} instance) + {{ + _Instance = instance; + +{GenerateMapperConfigurationForAutoMapper()} + }} + +{GeneratePrivateAutoMapper()} + }} +}}"; + private string GeneratePrivateAutoMapper() + { + return _context.ReplacedTypes.Count == 0 ? string.Empty : " private readonly IMapper _mapper;"; + } + + private string GenerateMapperConfigurationForAutoMapper() + { + if (_context.ReplacedTypes.Count == 0) + { + return string.Empty; + } + + var str = new StringBuilder(); + + str.AppendLine(" _mapper = new MapperConfiguration(cfg =>"); + str.AppendLine(" {"); + foreach (var replacedType in _context.ReplacedTypes) + { + str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();"); + str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();"); + } + str.AppendLine(" }).CreateMapper();"); + + return str.ToString(); + } + + private string GeneratePublicProperties(INamedTypeSymbol symbol, bool proxyAll) + { + var str = new StringBuilder(); + + foreach (var property in MemberHelper.GetPublicProperties(symbol)) + { + switch (property.GetTypeEnum()) + { + case TypeEnum.ValueTypeOrString: + case TypeEnum.Interface: + str.AppendLine($" public {property.ToPropertyTextForClass()}"); + str.AppendLine(); + break; + + default: + var type = GetPropertyType(property, out var isReplaced); + if (isReplaced) + { + str.AppendLine($" public {property.ToPropertyTextForClass(type)}"); + } + else + { + str.AppendLine($" public {property.ToPropertyTextForClass()}"); + } + str.AppendLine(); + break; + } + + } + + return str.ToString(); + } + + private string GeneratePublicMethods(INamedTypeSymbol symbol) + { + var str = new StringBuilder(); + foreach (var method in MemberHelper.GetPublicMethods(symbol)) + { + var methodParameters = new List(); + var invokeParameters = new List(); + + foreach (var ps in method.Parameters) + { + if (ps.GetTypeEnum() == TypeEnum.Complex) + { + var type = GetParameterType(ps, out var isReplaced); + methodParameters.Add($"{type} {ps.Name}"); + + if (isReplaced) + { + invokeParameters.Add($"_mapper.Map<{ps.Type}>({ps.Name})"); + } + else + { + invokeParameters.Add($"{ps.Name}"); + } + } + else + { + methodParameters.Add($"{ps.Type} {ps.Name}"); + + invokeParameters.Add($"{ps.Name}"); + } + } + + string returnTypeAsString; + string call = $"_Instance.{method.Name}({string.Join(", ", invokeParameters)})"; + if (method.ReturnType.GetTypeEnum() == TypeEnum.Complex) + { + returnTypeAsString = GetReplacedType(method.ReturnType, out var isReplaced); + if (isReplaced) + { + call = $"_mapper.Map<{returnTypeAsString}>(_Instance.{method.Name}({string.Join(", ", invokeParameters)}))"; + } + } + else + { + returnTypeAsString = method.ReturnType.ToString(); + } + + str.AppendLine($" public {returnTypeAsString} {method.Name}({string.Join(", ", methodParameters)}) => {call};"); + str.AppendLine(); + } + + return str.ToString(); + } + } } \ No newline at end of file