private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) { var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; builder .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {model.SourceType} {sourceClassParameterName})") .Indent() .Write(": this("); for (var i = 0; i < model.MappedProperties.Length; i++) { var property = model.MappedProperties[i]; if (property.TypeConverter is null) { if (property.IsEnumerable) { builder.Write( $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}.Select({mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.EnumerableTypeArgument}>).ToList()"); } else { builder.Write(property.MappedSourcePropertyTypeName is null ? $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}" : $"{property.Name}: {mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.Type}>({sourceClassParameterName}.{property.SourcePropertyName})"); } } else { var parameters = property.TypeConverterParameters.IsEmpty ? "null" : $"new object[] {{ {string.Join(", ", property.TypeConverterParameters)} }}"; builder.Write($"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); } if (i < model.MappedProperties.Length - 1) { builder.Write(", "); } } builder.WriteLine(")") .Unindent() .WriteOpeningBracket() .WriteLine($"if ({mappingContextParameterName} == null) throw new ArgumentNullException(nameof({mappingContextParameterName}));") .WriteLine($"if ({sourceClassParameterName} == null) throw new ArgumentNullException(nameof({sourceClassParameterName}));") .WriteLine() .WriteLine($"{mappingContextParameterName}.{MappingContextSource.RegisterMethodName}({sourceClassParameterName}, this);"); // End constructor declaration return(builder.WriteClosingBracket()); }
internal static SourceCode Generate(SourceGenerationOptions options) { using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteNullableContextOptionIf(options.SupportNullableReferenceTypes) .WriteLine() .WriteLine("using System;") .WriteLine() .WriteLine($"namespace {RootNamespace}") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Specifies the mapping behavior of the annotated property.") .WriteLine("/// </summary>") .WriteLine("/// <remarks>") .WriteLine($"/// {AttributeClassName} has a number of uses:") .WriteLine("/// <list type=\"bullet\">") .WriteLine("/// <item><description>By default properties with same name will get mapped. This attribute allows the names to be different.</description></item>") .WriteLine("/// <item><description>Indicates that a property should be mapped when member serialization is set to opt-in.</description></item>") .WriteLine("/// </list>") .WriteLine("/// </remarks>"); } builder .WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = true)]") .WriteLine($"public sealed class {AttributeClassName} : Attribute") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Gets or sets the property name of the object to mapping from.") .WriteLine("/// </summary>"); } builder .WriteLine($"public string{options.NullableReferenceSyntax} {SourcePropertyNamePropertyName} {{ get; set; }}") .WriteClosingBracket() // class .WriteClosingBracket(); // namespace return(new(builder.ToString(), $"{AttributeClassName}.g.cs")); }
private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model) { return(builder .WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {model.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") .WriteOpeningBracket() .GenerateSourceTypeExtensionMethod(model) .WriteClosingBracket()); }
private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model) { var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); if (model.Options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine($"/// Initializes a new instance of the <see cref=\"{model.TypeIdentifierName}\"/> class") .WriteLine($"/// using the property values from the specified <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine("/// </summary>") .WriteLine($"/// <exception cref=\"ArgumentNullException\">{sourceClassParameterName} is null</exception>"); } return(builder .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName})") .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}")); }
private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) { var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; var baseConstructor = model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" : string.Empty; builder .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {model.SourceType} {sourceClassParameterName}){baseConstructor}") .WriteOpeningBracket() .WriteLine($"if ({mappingContextParameterName} == null) throw new ArgumentNullException(nameof({mappingContextParameterName}));") .WriteLine($"if ({sourceClassParameterName} == null) throw new ArgumentNullException(nameof({sourceClassParameterName}));") .WriteLine() .WriteLine($"{mappingContextParameterName}.{MappingContextSource.RegisterMethodName}({sourceClassParameterName}, this);") .WriteLine(); foreach (var property in model.MappedProperties) { if (property.TypeConverter is null) { if (property.IsEnumerable) { builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName}.Select({mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.EnumerableTypeArgument}>).ToList();"); } else { builder.WriteLine(property.MappedSourcePropertyTypeName is null ? $"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};" : $"{property.Name} = {mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.Type}>({sourceClassParameterName}.{property.SourcePropertyName});"); } } else { var parameters = property.TypeConverterParameters.IsEmpty ? "null" : $"new object[] {{ {string.Join(", ", property.TypeConverterParameters)} }}"; builder.WriteLine($"{property.Name} = new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters});"); } } // End constructor declaration return(builder.WriteClosingBracket()); }
internal static SourceCode Generate(SourceGenerationOptions options) { using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteNullableContextOptionIf(options.SupportNullableReferenceTypes) .WriteLine() .WriteLine($"namespace {RootNamespace}") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Converts the value of <typeparamref name=\"TSource\"/> to <typeparamref name=\"TDestination\"/>.") .WriteLine("/// </summary>") .WriteLine("/// <typeparam name=\"TSource\">The type to convert from.</typeparam>") .WriteLine("/// <typeparam name=\"TDestination\">The type to convert to.</typeparam>"); } builder .WriteLine($"public interface {InterfaceName}<in TSource, out TDestination>") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Converts the value of <paramref name=\"source\"/> object to <typeparamref name=\"TDestination\"/>.") .WriteLine("/// </summary>") .WriteLine("/// <param name=\"source\">The <see cref=\"TSource\"/> to convert.</param>") .WriteLine($"/// <param name=\"converterParameters\">The parameter list passed to the <see cref=\"{MapTypeConverterAttributeSource.AttributeClassName}\"/></param>") .WriteLine("/// <returns><typeparamref name=\"TDestination\"/> object.</returns>"); } builder .WriteLine($"TDestination Convert(TSource source, object[]{options.NullableReferenceSyntax} converterParameters);") .WriteClosingBracket() .WriteClosingBracket(); return(new(builder.ToString(), $"{InterfaceName}.g.cs")); }
internal static SourceCode Generate(SourceGenerationOptions options) { var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteLine("using System;") .WriteLine() .WriteLine($"namespace {RootNamespace}") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Specifies that the annotated property should be excluded.") .WriteLine("/// </summary>"); } builder .WriteLine("[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]") .WriteLine($"public sealed class {AttributeClassName} : Attribute {{ }}") .WriteClosingBracket(); return(new(builder.ToString(), $"{AttributeClassName}.g.cs")); }
private static SourceBuilder GenerateConvertorMethodsXmlDocs(this SourceBuilder builder, MappingModel model, string sourceClassParameterName) { if (!model.Options.GenerateXmlDocument) { return(builder); } return(builder .WriteLine("/// <summary>") .WriteLine($"/// Creates a new instance of <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties") .WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine("/// </summary>") .WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>") .WriteLine($"/// <returns>A new instance of <see cred=\"{model.TypeIdentifierName}\"/> -or- <c>null</c> if <paramref name=\"{sourceClassParameterName}\"/> is <c>null</c>.</returns>")); }
internal static SourceCode Generate(SourceGenerationOptions options) { using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteLine("using System;") .WriteLine() .WriteLine($"namespace {RootNamespace}") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Specifies that the annotated class can be mapped from the provided <see cref=\"SourceType\"/>.") .WriteLine("/// </summary>"); } builder .WriteLine("[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]") .WriteLine($"public sealed class {AttributeName}Attribute : Attribute") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine($"/// Initializes a new instance of the <see cref=\"{AttributeName}Attribute\"/> class with the specified <paramref name=\"sourceType\"/>.") .WriteLine("/// </summary>") .WriteLine("/// <param name=\"sourceType\">The type of to map from.</param>"); } builder .WriteLine($"public {AttributeName}Attribute(Type sourceType)") .WriteOpeningBracket() .WriteLine("SourceType = sourceType;") .WriteClosingBracket() .WriteLine(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Gets the type to map from.") .WriteLine("/// </summary>"); } builder .WriteLine("public Type SourceType { get; }") .WriteClosingBracket() // class .WriteClosingBracket(); // namespace return(new(builder.ToString(), $"{AttributeName}Attribute.g.cs")); }
internal static SourceCode Generate(SourceGenerationOptions options) { using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteNullableContextOptionIf(options.SupportNullableReferenceTypes) .WriteLine() .WriteLine("using System;") .WriteLine() .WriteLine($"namespace {RootNamespace}") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine("/// Specifies what type to use as a converter for the property this attribute is bound to.") .WriteLine("/// </summary>"); } builder .WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false)]") .WriteLine($"public sealed class {AttributeClassName} : Attribute") .WriteOpeningBracket(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine($"/// Initializes a new instance of <see cref=\"{AttributeClassName}\"/>.") .WriteLine("/// </summary>") .WriteLine($"/// <param name=\"converter\">The <see cref=\"{ITypeConverterSource.InterfaceName}{{TSource,TDestination}}\" /> to be used to convert the source type.</param>") .WriteLine("/// <param name=\"converterParameters\">The list of parameters to pass to the <paramref name=\"converter\"/> during the type conversion.</param>"); } builder .WriteLine($"public {AttributeClassName}(Type converter, object[]{options.NullableReferenceSyntax} converterParameters = null)") .WriteOpeningBracket() .WriteLine($"{ConverterPropertyName} = converter;") .WriteLine($"{ConverterParametersPropertyName} = converterParameters;") .WriteClosingBracket() .WriteLine(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine($"/// Gets or sets the <see cref=\"{ITypeConverterSource.InterfaceName}{{TSource,TDestination}}\" /> to be used to convert the source type.") .WriteLine("/// </summary>"); } builder .WriteLine($"public Type {ConverterPropertyName} {{ get; }}") .WriteLine(); if (options.GenerateXmlDocument) { builder .WriteLine("/// <summary>") .WriteLine($"/// Gets the list of parameters to pass to the <see cref=\"{ConverterPropertyName}\"/> during the type conversion.") .WriteLine("/// </summary>"); } builder .WriteLine($"public object[]{options.NullableReferenceSyntax} {ConverterParametersPropertyName} {{ get; }}") .WriteClosingBracket() .WriteClosingBracket(); return(new(builder.ToString(), $"{AttributeClassName}.g.cs")); }