Add MapProperty attribute.
This commit is contained in:
parent
e9e44b979a
commit
ec21abcf0e
|
@ -35,7 +35,7 @@ namespace MapTo.Extensions
|
||||||
|
|
||||||
internal static string GetBuildPropertyName(string propertyName) => $"build_property.{PropertyNameSuffix}{propertyName}";
|
internal static string GetBuildPropertyName(string propertyName) => $"build_property.{PropertyNameSuffix}{propertyName}";
|
||||||
|
|
||||||
internal static void AddSource(this GeneratorExecutionContext context, Source source) =>
|
internal static void AddSource(this GeneratorExecutionContext context, SourceCode sourceCode) =>
|
||||||
context.AddSource(source.HintName, source.Code);
|
context.AddSource(sourceCode.HintName, sourceCode.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@ namespace MapTo
|
||||||
context.AddSource(MapFromAttributeSource.Generate(options));
|
context.AddSource(MapFromAttributeSource.Generate(options));
|
||||||
context.AddSource(IgnorePropertyAttributeSource.Generate(options));
|
context.AddSource(IgnorePropertyAttributeSource.Generate(options));
|
||||||
context.AddSource(TypeConverterSource.Generate(options));
|
context.AddSource(TypeConverterSource.Generate(options));
|
||||||
|
context.AddSource(MapPropertyAttributeSource.Generate(options));
|
||||||
|
|
||||||
if (context.SyntaxReceiver is MapToSyntaxReceiver receiver && receiver.CandidateClasses.Any())
|
if (context.SyntaxReceiver is MapToSyntaxReceiver receiver && receiver.CandidateClasses.Any())
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace MapTo.Sources
|
||||||
{
|
{
|
||||||
internal const string AttributeName = "IgnoreProperty";
|
internal const string AttributeName = "IgnoreProperty";
|
||||||
|
|
||||||
internal static Source Generate(SourceGenerationOptions options)
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
{
|
{
|
||||||
var builder = new SourceBuilder()
|
var builder = new SourceBuilder()
|
||||||
.WriteLine(GeneratedFilesHeader)
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace MapTo.Sources
|
||||||
{
|
{
|
||||||
internal static class MapClassSource
|
internal static class MapClassSource
|
||||||
{
|
{
|
||||||
internal static Source Generate(MapModel model)
|
internal static SourceCode Generate(MapModel model)
|
||||||
{
|
{
|
||||||
using var builder = new SourceBuilder()
|
using var builder = new SourceBuilder()
|
||||||
.WriteLine(GeneratedFilesHeader)
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace MapTo.Sources
|
||||||
{
|
{
|
||||||
internal const string AttributeName = "MapFrom";
|
internal const string AttributeName = "MapFrom";
|
||||||
|
|
||||||
internal static Source Generate(SourceGenerationOptions options)
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
{
|
{
|
||||||
using var builder = new SourceBuilder()
|
using var builder = new SourceBuilder()
|
||||||
.WriteLine(GeneratedFilesHeader)
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
using MapTo.Models;
|
||||||
|
using static MapTo.Sources.Constants;
|
||||||
|
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
internal static class MapPropertyAttributeSource
|
||||||
|
{
|
||||||
|
internal const string AttributeName = "MapProperty";
|
||||||
|
|
||||||
|
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("/// Maps a property to property of another object.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]")
|
||||||
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Initializes a new instance of <see cref=\"MapPropertyAttribute\"/>.")
|
||||||
|
.WriteLine("/// </summary>")
|
||||||
|
.WriteLine("/// <param name=\"converter\">The <see cref=\"ITypeConverter{TSource,TDestination}\" /> to convert the value of the annotated property.</param>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine($"public {AttributeName}Attribute(Type converter = null)")
|
||||||
|
.WriteOpeningBracket()
|
||||||
|
.WriteLine("Converter = converter;")
|
||||||
|
.WriteClosingBracket()
|
||||||
|
.WriteLine();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Gets the <see cref=\"ITypeConverter{TSource,TDestination}\" /> to convert the value of the annotated property.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("public Type Converter { get; }")
|
||||||
|
.WriteClosingBracket()
|
||||||
|
.WriteClosingBracket();
|
||||||
|
|
||||||
|
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
namespace MapTo.Sources
|
|
||||||
{
|
|
||||||
internal record Source(string Code, string HintName);
|
|
||||||
}
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
internal record SourceCode(string Text, string HintName);
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ namespace MapTo.Sources
|
||||||
{
|
{
|
||||||
internal const string InterfaceName = "ITypeConverter";
|
internal const string InterfaceName = "ITypeConverter";
|
||||||
|
|
||||||
internal static Source Generate(SourceGenerationOptions options)
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
{
|
{
|
||||||
using var builder = new SourceBuilder()
|
using var builder = new SourceBuilder()
|
||||||
.WriteLine(GeneratedFilesHeader)
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
|
|
@ -512,5 +512,37 @@ namespace MapTo
|
||||||
diagnostics.ShouldBeSuccessful();
|
diagnostics.ShouldBeSuccessful();
|
||||||
compilation.SyntaxTrees.ShouldContainSource(TypeConverterSource.InterfaceName, expectedInterface);
|
compilation.SyntaxTrees.ShouldContainSource(TypeConverterSource.InterfaceName, expectedInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void VerifyMapPropertyAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
const string source = "";
|
||||||
|
var expectedInterface = $@"
|
||||||
|
{Constants.GeneratedFilesHeader}
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MapTo
|
||||||
|
{{
|
||||||
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
|
||||||
|
public sealed class MapPropertyAttribute : Attribute
|
||||||
|
{{
|
||||||
|
public MapPropertyAttribute(Type converter = null)
|
||||||
|
{{
|
||||||
|
Converter = converter;
|
||||||
|
}}
|
||||||
|
|
||||||
|
public Type Converter {{ get; }}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
".Trim();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
diagnostics.ShouldBeSuccessful();
|
||||||
|
compilation.SyntaxTrees.ShouldContainSource(MapPropertyAttributeSource.AttributeName, expectedInterface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,10 @@ namespace TestConsoleApp.ViewModels
|
||||||
[MapFrom(typeof(Data.Models.User))]
|
[MapFrom(typeof(Data.Models.User))]
|
||||||
public partial class User
|
public partial class User
|
||||||
{
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
|
||||||
public string FirstName { get; }
|
public string FirstName { get; }
|
||||||
|
|
||||||
|
public string LastName { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,16 @@ namespace TestConsoleApp.ViewModels
|
||||||
{
|
{
|
||||||
public string FirstName { get; }
|
public string FirstName { get; }
|
||||||
|
|
||||||
// [IgnoreProerty]
|
[IgnoreProperty]
|
||||||
public string LastName { get; }
|
public string LastName { get; }
|
||||||
|
|
||||||
|
[MapProperty(converter: typeof(LastNameConverter))]
|
||||||
|
public string Key { get; }
|
||||||
|
|
||||||
|
private class LastNameConverter : ITypeConverter<int, string>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Convert(int source) => $"{source} :: With Type Converter";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue