Esempio n. 1
0
        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());
        }
Esempio n. 2
0
        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"));
        }
Esempio n. 3
0
 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());
 }
Esempio n. 4
0
        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}) {{ }}"));
        }
Esempio n. 5
0
        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());
        }
Esempio n. 6
0
        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"));
        }
Esempio n. 7
0
        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"));
        }
Esempio n. 8
0
        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>"));
        }
Esempio n. 9
0
        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"));
        }