diff --git a/src-examples/ProxyInterfaceConsumer/Person.cs b/src-examples/ProxyInterfaceConsumer/Person.cs index 6fcedad..bfdb3f6 100644 --- a/src-examples/ProxyInterfaceConsumer/Person.cs +++ b/src-examples/ProxyInterfaceConsumer/Person.cs @@ -16,7 +16,7 @@ namespace ProxyInterfaceConsumer public List
AddressesLIst { get; set; } - public Dictionary AddressesDict { get; set; } + public Dictionary AddressesDict { get; set; } = new Dictionary(); public E E { get; set; } @@ -25,6 +25,11 @@ namespace ProxyInterfaceConsumer return 600; } + public void AddAddress(Address a) + { + AddressesDict.Add($"{AddressesDict.Count}", a); + } + public void Void() { // diff --git a/src-examples/ProxyInterfaceConsumer/Program.cs b/src-examples/ProxyInterfaceConsumer/Program.cs index f5beef9..b05a868 100644 --- a/src-examples/ProxyInterfaceConsumer/Program.cs +++ b/src-examples/ProxyInterfaceConsumer/Program.cs @@ -8,9 +8,6 @@ namespace ProxyInterfaceConsumer { public static void Main() { - - - var c = new Clazz { Name = "n" @@ -29,7 +26,10 @@ namespace ProxyInterfaceConsumer IPerson p = new PersonProxy(new Person()); p.Name = "test"; - p.Address = new AddressProxy(new Address { HouseNumber = 42 }); + var ap = new AddressProxy(new Address { HouseNumber = 42 }); + p.Address = ap; + p.AddAddress(ap); + p.AddAddress(new AddressProxy(new Address { HouseNumber = 1000 })); //p.MyNamedTypeSymbol = null; //p.Compilation = null; diff --git a/src/ProxyInterfaceSourceGenerator/Context.cs b/src/ProxyInterfaceSourceGenerator/Context.cs index 585042c..d289fdc 100644 --- a/src/ProxyInterfaceSourceGenerator/Context.cs +++ b/src/ProxyInterfaceSourceGenerator/Context.cs @@ -12,5 +12,7 @@ namespace ProxyInterfaceSourceGenerator public List GeneratedData { get; } = new List(); public IDictionary CandidateInterfaces { get; init; } - } + + public Dictionary ReplacedTypes { get; } = new Dictionary(); +} } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs index 87fdfe3..442bbc2 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using ProxyInterfaceSourceGenerator.Enums; namespace ProxyInterfaceSourceGenerator.Extensions @@ -12,7 +11,22 @@ namespace ProxyInterfaceSourceGenerator.Extensions { return TypeEnum.ValueTypeOrString; } - + + if (p.Type.TypeKind == TypeKind.Interface) + { + return TypeEnum.Interface; + } + + return TypeEnum.Complex; + } + + public static TypeEnum GetTypeEnum(this IParameterSymbol p) + { + if (p.Type.IsValueType || p.Type.ToString() == "string") + { + return TypeEnum.ValueTypeOrString; + } + if (p.Type.TypeKind == TypeKind.Interface) { return TypeEnum.Interface; @@ -46,36 +60,5 @@ namespace ProxyInterfaceSourceGenerator.Extensions return $"{overrideType} {property.Name} {{ {get}{set}}}"; } - - //public static string ToPropertyTextForClass(this IPropertySymbol property, string overrideType, string className) - //{ - // var classNameProxy = $"{className}Proxy"; - // var get = property.GetMethod != null ? $"get => new {classNameProxy}(_Instance.{property.Name}); " : string.Empty; - // var set = property.SetMethod != null ? $"set => _Instance.{property.Name} = (({classNameProxy}) value)._Instance; " : string.Empty; - - // return $"{overrideType} {property.Name} {{ {get}{set}}}"; - //} - - public static string ToMethodText(this IMethodSymbol method) - { - var parameters = new List(); - foreach (var ps in method.Parameters) - { - parameters.Add($"{ps.Type} {ps.Name}"); - } - - return $"{method.ReturnType} {method.Name}({string.Join(", ", parameters)})"; - } - - public static string ToMethodTextForClass(this IMethodSymbol method) - { - var parameters = new List(); - foreach (var ps in method.Parameters) - { - parameters.Add($"{ps.Name}"); - } - - return $"{method.ToMethodText()} => _Instance.{method.Name}({string.Join(", ", parameters)});"; - } } } diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs index a599a2f..013a057 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; +// using AnyOfTypes; using Microsoft.CodeAnalysis; namespace ProxyInterfaceSourceGenerator.FileGenerators @@ -14,39 +14,122 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators _context = context; } - protected string GetPropertyType(IPropertySymbol property, out Dictionary differs) - { - differs = new Dictionary(); + //protected string GetReplacedType(AnyOf x) + //{ + // ITypeSymbol ts = x.IsFirst ? x.First.Type : x.Second.Type; + // var propertyTypeAsString = ts.ToString(); - var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == property.Type.ToString()); + // var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == propertyTypeAsString); + // if (existing is not null) + // { + // if (!_context.ReplacedTypes.ContainsKey(propertyTypeAsString)) + // { + // _context.ReplacedTypes.Add(propertyTypeAsString, existing.InterfaceName); + // } + + // return existing.InterfaceName; + // } + + // if (ts is INamedTypeSymbol namedTypedSymbol) + // { + // var propertyTypeAsStringToBeModified = propertyTypeAsString; + // foreach (var typeArgument in namedTypedSymbol.TypeArguments) + // { + // var typeArgumentAsString = typeArgument.ToString(); + // var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeArgumentAsString); + // if (exist is not null) + // { + // if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) + // { + // _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); + // } + + // propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName); + // } + // } + + // return propertyTypeAsStringToBeModified; + // } + + // return propertyTypeAsString; + //} + + protected string GetPropertyType(IPropertySymbol property) + { + var propertyTypeAsString = property.Type.ToString(); + + var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == propertyTypeAsString); if (existing is not null) { - differs.Add(property.Type.ToString(), existing.InterfaceName); + if (!_context.ReplacedTypes.ContainsKey(propertyTypeAsString)) + { + _context.ReplacedTypes.Add(propertyTypeAsString, existing.InterfaceName); + } + return existing.InterfaceName; } if (property.Type is INamedTypeSymbol namedTypedSymbol) { - var type = property.Type.ToString(); + var propertyTypeAsStringToBeModified = propertyTypeAsString; foreach (var typeArgument in namedTypedSymbol.TypeArguments) { - var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeArgument.ToString()); - + var typeArgumentAsString = typeArgument.ToString(); + var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeArgumentAsString); if (exist is not null) { - if (!differs.ContainsKey(typeArgument.ToString())) + if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) { - differs.Add(typeArgument.ToString(), exist.InterfaceName); + _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); } - type = type.Replace(typeArgument.ToString(), exist.InterfaceName); + propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName); } } - return type; + return propertyTypeAsStringToBeModified; } - return property.Type.ToString(); + return propertyTypeAsString; + } + + protected string GetParameterType(IParameterSymbol property) + { + var propertyTypeAsString = property.Type.ToString(); + + var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == propertyTypeAsString); + if (existing is not null) + { + if (!_context.ReplacedTypes.ContainsKey(propertyTypeAsString)) + { + _context.ReplacedTypes.Add(propertyTypeAsString, existing.InterfaceName); + } + + return existing.InterfaceName; + } + + if (property.Type is INamedTypeSymbol namedTypedSymbol) + { + var propertyTypeAsStringToBeModified = propertyTypeAsString; + foreach (var typeArgument in namedTypedSymbol.TypeArguments) + { + var typeArgumentAsString = typeArgument.ToString(); + var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == typeArgumentAsString); + if (exist is not null) + { + if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) + { + _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); + } + + propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName); + } + } + + return propertyTypeAsStringToBeModified; + } + + return propertyTypeAsString; } protected INamedTypeSymbol GetType(string name) diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs index ea292d1..1ccebe7 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs @@ -10,8 +10,6 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators { internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator { - private readonly List files = new List(); - public PartialInterfacesGenerator(Context context) : base(context) { @@ -21,11 +19,8 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators { foreach (var ci in _context.CandidateInterfaces) { - var file = GenerateFile(ci.Value.InterfaceName, ci.Value.TypeName, ci.Value.ProxyAll); - files.Add(file); + yield return GenerateFile(ci.Value.InterfaceName, ci.Value.TypeName, ci.Value.ProxyAll); } - - return files; } private FileData GenerateFile(string interfaceName, string typeName, bool proxyAll) @@ -75,38 +70,8 @@ namespace {symbol.ContainingNamespace} // ComplexProperties foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Complex)) { - //if (proxyAll) - //{ - // var existing = _context.GeneratedData - // .FirstOrDefault(x => x.ClassName == $"{property.Name}Proxy" || x.InterfaceName == $"I{property.Name}"); - - // if (existing is not null) - // { - // str.AppendLine($" {property.ToPropertyText(existing.InterfaceName)}"); - // } - // else - // { - // // Create new - // var typeName = $"{property.Type}"; - // var file = GenerateFile($"I{property.Name}", typeName, false); - // str.AppendLine($" // {property.ToPropertyText($"I{property.Name}")}"); - // } - //} - //else - - var type = GetPropertyType(property, out _); + var type = GetPropertyType(property); str.AppendLine($" {property.ToPropertyText(type)}"); - - //var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == property.Type.ToString()); - //if (existing is not null) - //{ - // str.AppendLine($" {property.ToPropertyText(existing.InterfaceName)}"); - //} - //else - //{ - // str.AppendLine($" {property.ToPropertyText()}"); - //} - str.AppendLine(); } @@ -118,8 +83,25 @@ namespace {symbol.ContainingNamespace} var str = new StringBuilder(); foreach (var method in MemberHelper.GetPublicMethods(symbol)) { - str.AppendLine($" {method.ToMethodText()};"); + 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($" {method.ReturnType} {method.Name}({string.Join(", ", methodParameters)});"); str.AppendLine(); + + //str.AppendLine($" {method.ToMethodText()};"); + //str.AppendLine(); } return str.ToString(); diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs index 96c1b57..a53c7b2 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using ProxyInterfaceSourceGenerator.Enums; @@ -10,10 +9,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators { internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator { - private readonly List files = new List(); - - public ProxyClassesGenerator(Context context) : - base(context) + public ProxyClassesGenerator(Context context) : base(context) { } @@ -21,11 +17,8 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators { foreach (var ci in _context.CandidateInterfaces) { - var file = GenerateFile(ci.Value.InterfaceName, ci.Value.ClassName, ci.Value.TypeName, ci.Value.ProxyAll); - files.Add(file); + yield return GenerateFile(ci.Value.InterfaceName, ci.Value.ClassName, ci.Value.TypeName, ci.Value.ProxyAll); } - - return files; } private FileData GenerateFile(string interfaceName, string className, string typeName, bool proxyAll) @@ -53,16 +46,16 @@ namespace {symbol.ContainingNamespace} public {className} _Instance {{ get; }} +{GeneratePublicProperties(symbol, proxyAll)} + +{GeneratePublicMethods(symbol)} + public {className}Proxy({className} instance) {{ _Instance = instance; {GenerateAutoMapper()} }} - -{GeneratePublicProperties(symbol, proxyAll)} - -{GeneratePublicMethods(symbol)} }} }}"; @@ -70,14 +63,14 @@ namespace {symbol.ContainingNamespace} { var str = new StringBuilder(); - str.AppendLine(" _mapper = new MapperConfiguration(cfg =>"); - str.AppendLine(" {"); - foreach (var x in _context.CandidateInterfaces) + str.AppendLine(" _mapper = new MapperConfiguration(cfg =>"); + str.AppendLine(" {"); + foreach (var replacedType in _context.ReplacedTypes) { - str.AppendLine($" cfg.CreateMap<{x.Value.InterfaceName}, {x.Value.ClassName}>();"); - str.AppendLine($" cfg.CreateMap<{x.Value.ClassName}, {x.Value.InterfaceName}>();"); + str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();"); + str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();"); } - str.AppendLine(" }).CreateMapper();"); + str.AppendLine(" }).CreateMapper();"); return str.ToString(); } @@ -103,52 +96,8 @@ namespace {symbol.ContainingNamespace} // ComplexProperties foreach (var property in MemberHelper.GetPublicProperties(symbol, p => p.GetTypeEnum() == TypeEnum.Complex)) { - var type = GetPropertyType(property, out var differs); - if (!differs.Any()) - { - str.AppendLine($" public {property.ToPropertyTextForClass()}"); - } - else - { - str.AppendLine($" public {property.ToPropertyTextForClass(type)}"); - // var get = property.GetMethod != null ? $"get => _mapper.Map<{type}>(_Instance.{property.Name}); " : string.Empty; - // var set = property.SetMethod != null ? $"set => _Instance.{property.Name} = _mapper.Map<{property.Type}>(value);" : string.Empty; - //var p = $"{type} {property.Name} {{ {get}{set}}}"; - //str.AppendLine($" public {type} {property.Name} {{ {get}{set}}}"); - } - - /* - public IList Cs - { - get => _mapper.Map>(_instance.Cs); - - set => _instance.Cs = _mapper.Map>(value); - } - }*/ - - - //public static string ToPropertyTextForClass(this IPropertySymbol property, string overrideType) - //{ - // // var classNameProxy = $"Proxy"; - // var get = property.GetMethod != null ? $"get => _mapper.Map<{overrideType}>(_Instance.{property.Name}); " : string.Empty; - // var set = property.SetMethod != null ? $"set => _mapper.Map<{property.Type}>( = (({classNameProxy}) value)._Instance; " : string.Empty; - - // return $"{overrideType} {property.Name} {{ {get}{set}}}"; - //} - - - //str.AppendLine($" public {property.ToPropertyTextForClass(type)}"); - - //var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.TypeName == property.Type.ToString()); - //if (existing is not null) - //{ - // str.AppendLine($" public {property.ToPropertyTextForClass(existing.InterfaceName, existing.ClassName)}"); - //} - //else - //{ - // str.AppendLine($" public {property.ToPropertyTextForClass()}"); - //} - + var type = GetPropertyType(property); + str.AppendLine($" public {property.ToPropertyTextForClass(type)}"); str.AppendLine(); } @@ -160,7 +109,34 @@ namespace {symbol.ContainingNamespace} var str = new StringBuilder(); foreach (var method in MemberHelper.GetPublicMethods(symbol)) { - str.AppendLine($" public {method.ToMethodTextForClass()}"); + 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}"); + } + } + + var invokeParameters = new List(); + foreach (var ps in method.Parameters) + { + if (ps.GetTypeEnum() == TypeEnum.Complex) + { + invokeParameters.Add($"_mapper.Map<{ps.Type}>({ps.Name})"); + } + else + { + invokeParameters.Add($"{ps.Name}"); + } + } + + str.AppendLine($" public {method.ReturnType} {method.Name}({string.Join(", ", methodParameters)}) => _Instance.{method.Name}({string.Join(", ", invokeParameters)});"); str.AppendLine(); } diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs index e5c8f01..75beffc 100644 --- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs @@ -43,8 +43,8 @@ namespace ProxyInterfaceSourceGenerator context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8)); } - var classesGenerator = new ProxyClassesGenerator(context); - foreach (var data in classesGenerator.GenerateFiles()) + var proxyClassesGenerator = new ProxyClassesGenerator(context); + foreach (var data in proxyClassesGenerator.GenerateFiles()) { context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8)); } diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj index bcac399..f524e55 100644 --- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj +++ b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj @@ -31,6 +31,7 @@ + all