Skip to content

Commit 7210aab

Browse files
Support attributes on input parameters (#128)
1 parent fde50b9 commit 7210aab

10 files changed

+492
-4
lines changed

src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.Models.cs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ private sealed record Behavior
1919
[ExcludeFromCodeCoverage]
2020
private sealed record Parameter
2121
{
22+
public required string? Attributes { get; init; }
2223
public required string Type { get; init; }
2324
public required string Name { get; init; }
2425
}

src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.TransformHandler.cs

+42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Diagnostics.CodeAnalysis;
22
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.CSharp;
34

45
namespace Immediate.Handlers.Generators.ImmediateHandlers;
56

@@ -61,6 +62,7 @@ CancellationToken cancellationToken
6162
.Take(handleMethod.Parameters.Length - (useToken ? 2 : 1))
6263
.Select(p => new Parameter
6364
{
65+
Attributes = p.GetAttributesString(),
6466
Type = p.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
6567
Name = p.Name,
6668
})
@@ -136,4 +138,44 @@ file static class Extensions
136138
symbol
137139
.GetAttributes()
138140
.FirstOrDefault(a => a.AttributeClass.IsBehaviorsAttribute());
141+
142+
public static string? GetAttributesString(this IParameterSymbol parameter)
143+
{
144+
var attributes = parameter.GetAttributes();
145+
if (attributes.Length == 0)
146+
return null;
147+
148+
return $"[{string.Join(", ", attributes.Select(GetAttributeString))}] ";
149+
}
150+
151+
private static string GetAttributeString(AttributeData attributeData)
152+
{
153+
var @class = attributeData.AttributeClass!.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
154+
155+
var parameters = new List<string>();
156+
157+
foreach (var tc in attributeData.ConstructorArguments)
158+
{
159+
if (tc.GetTypedConstantString() is { } str)
160+
parameters.Add(str);
161+
}
162+
163+
foreach (var na in attributeData.NamedArguments)
164+
{
165+
if (na.Value.GetTypedConstantString() is { } str)
166+
parameters.Add($"{na.Key} = {str}");
167+
}
168+
169+
return parameters.Count == 0
170+
? @class
171+
: $"{@class}({string.Join(", ", parameters)})";
172+
}
173+
174+
[SuppressMessage("Style", "IDE0072:Add missing cases")]
175+
private static string? GetTypedConstantString(this TypedConstant tc) =>
176+
tc.Kind switch
177+
{
178+
TypedConstantKind.Array => $"[{string.Join(", ", tc.Values.Select(GetTypedConstantString))}]",
179+
_ => tc.ToCSharpString(),
180+
};
139181
}

src/Immediate.Handlers.Generators/Templates/Handler.sbntxt

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ partial class {{ class_name }}
6868

6969
public HandleBehavior(
7070
{{~ for parameter in handler_parameters ~}}
71-
{{ parameter.type }} {{ parameter.name }}{{ if !for.last }},{{ end }}
71+
{{ parameter.attributes }}{{ parameter.type }} {{ parameter.name }}{{ if !for.last }},{{ end }}
7272
{{~ end ~}}
7373
)
7474
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//HintName: IH.Dummy.GetUsersQuery.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
#pragma warning disable CS1591
5+
6+
namespace Dummy;
7+
8+
partial class GetUsersQuery
9+
{
10+
public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>
11+
{
12+
private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior;
13+
14+
public Handler(
15+
global::Dummy.GetUsersQuery.HandleBehavior handleBehavior
16+
)
17+
{
18+
var handlerType = typeof(GetUsersQuery);
19+
20+
_handleBehavior = handleBehavior;
21+
22+
}
23+
24+
public async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
25+
global::Dummy.GetUsersQuery.Query request,
26+
global::System.Threading.CancellationToken cancellationToken = default
27+
)
28+
{
29+
return await _handleBehavior
30+
.HandleAsync(request, cancellationToken)
31+
.ConfigureAwait(false);
32+
}
33+
}
34+
35+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
36+
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Dummy.GetUsersQuery.Query, int>
37+
{
38+
private readonly global::Dummy.Service _service;
39+
40+
public HandleBehavior(
41+
[global::Dummy.TestAttribute(["Dummy1", "Dummy2"], ["Dummy1", "Dummy2"], ["Dummy3", "Dummy4"])] global::Dummy.Service service
42+
)
43+
{
44+
_service = service;
45+
}
46+
47+
public override async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
48+
global::Dummy.GetUsersQuery.Query request,
49+
global::System.Threading.CancellationToken cancellationToken
50+
)
51+
{
52+
return await global::Dummy.GetUsersQuery
53+
.HandleAsync(
54+
request
55+
, _service
56+
, cancellationToken
57+
)
58+
.ConfigureAwait(false);
59+
}
60+
}
61+
62+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
63+
public static IServiceCollection AddHandlers(
64+
IServiceCollection services,
65+
ServiceLifetime lifetime = ServiceLifetime.Scoped
66+
)
67+
{
68+
services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
69+
services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
70+
services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime));
71+
return services;
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//HintName: IH.ServiceCollectionExtensions.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.DependencyInjection.Extensions;
4+
5+
#pragma warning disable CS1591
6+
7+
public static class HandlerServiceCollectionExtensions
8+
{
9+
public static IServiceCollection AddBehaviors(
10+
this IServiceCollection services)
11+
{
12+
13+
return services;
14+
}
15+
16+
public static IServiceCollection AddHandlers(
17+
this IServiceCollection services,
18+
ServiceLifetime lifetime = ServiceLifetime.Scoped
19+
)
20+
{
21+
global::Dummy.GetUsersQuery.AddHandlers(services, lifetime);
22+
23+
return services;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//HintName: IH.Dummy.GetUsersQuery.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
#pragma warning disable CS1591
5+
6+
namespace Dummy;
7+
8+
partial class GetUsersQuery
9+
{
10+
public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>
11+
{
12+
private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior;
13+
14+
public Handler(
15+
global::Dummy.GetUsersQuery.HandleBehavior handleBehavior
16+
)
17+
{
18+
var handlerType = typeof(GetUsersQuery);
19+
20+
_handleBehavior = handleBehavior;
21+
22+
}
23+
24+
public async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
25+
global::Dummy.GetUsersQuery.Query request,
26+
global::System.Threading.CancellationToken cancellationToken = default
27+
)
28+
{
29+
return await _handleBehavior
30+
.HandleAsync(request, cancellationToken)
31+
.ConfigureAwait(false);
32+
}
33+
}
34+
35+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
36+
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Dummy.GetUsersQuery.Query, int>
37+
{
38+
private readonly global::Dummy.SomeKeyedService _service;
39+
40+
public HandleBehavior(
41+
[global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey"), global::Dummy.TestAttribute(Message = "Test"), global::Dummy.Test2Attribute] global::Dummy.SomeKeyedService service
42+
)
43+
{
44+
_service = service;
45+
}
46+
47+
public override async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
48+
global::Dummy.GetUsersQuery.Query request,
49+
global::System.Threading.CancellationToken cancellationToken
50+
)
51+
{
52+
return await global::Dummy.GetUsersQuery
53+
.HandleAsync(
54+
request
55+
, _service
56+
, cancellationToken
57+
)
58+
.ConfigureAwait(false);
59+
}
60+
}
61+
62+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
63+
public static IServiceCollection AddHandlers(
64+
IServiceCollection services,
65+
ServiceLifetime lifetime = ServiceLifetime.Scoped
66+
)
67+
{
68+
services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
69+
services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
70+
services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime));
71+
return services;
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//HintName: IH.ServiceCollectionExtensions.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.DependencyInjection.Extensions;
4+
5+
#pragma warning disable CS1591
6+
7+
public static class HandlerServiceCollectionExtensions
8+
{
9+
public static IServiceCollection AddBehaviors(
10+
this IServiceCollection services)
11+
{
12+
13+
return services;
14+
}
15+
16+
public static IServiceCollection AddHandlers(
17+
this IServiceCollection services,
18+
ServiceLifetime lifetime = ServiceLifetime.Scoped
19+
)
20+
{
21+
global::Dummy.GetUsersQuery.AddHandlers(services, lifetime);
22+
23+
return services;
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//HintName: IH.Dummy.GetUsersQuery.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
#pragma warning disable CS1591
5+
6+
namespace Dummy;
7+
8+
partial class GetUsersQuery
9+
{
10+
public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>
11+
{
12+
private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior;
13+
14+
public Handler(
15+
global::Dummy.GetUsersQuery.HandleBehavior handleBehavior
16+
)
17+
{
18+
var handlerType = typeof(GetUsersQuery);
19+
20+
_handleBehavior = handleBehavior;
21+
22+
}
23+
24+
public async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
25+
global::Dummy.GetUsersQuery.Query request,
26+
global::System.Threading.CancellationToken cancellationToken = default
27+
)
28+
{
29+
return await _handleBehavior
30+
.HandleAsync(request, cancellationToken)
31+
.ConfigureAwait(false);
32+
}
33+
}
34+
35+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
36+
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Dummy.GetUsersQuery.Query, int>
37+
{
38+
private readonly global::Dummy.SomeKeyedService _service;
39+
40+
public HandleBehavior(
41+
[global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey")] global::Dummy.SomeKeyedService service
42+
)
43+
{
44+
_service = service;
45+
}
46+
47+
public override async global::System.Threading.Tasks.ValueTask<int> HandleAsync(
48+
global::Dummy.GetUsersQuery.Query request,
49+
global::System.Threading.CancellationToken cancellationToken
50+
)
51+
{
52+
return await global::Dummy.GetUsersQuery
53+
.HandleAsync(
54+
request
55+
, _service
56+
, cancellationToken
57+
)
58+
.ConfigureAwait(false);
59+
}
60+
}
61+
62+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
63+
public static IServiceCollection AddHandlers(
64+
IServiceCollection services,
65+
ServiceLifetime lifetime = ServiceLifetime.Scoped
66+
)
67+
{
68+
services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
69+
services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, int>), typeof(global::Dummy.GetUsersQuery.Handler), lifetime));
70+
services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime));
71+
return services;
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//HintName: IH.ServiceCollectionExtensions.g.cs
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.DependencyInjection.Extensions;
4+
5+
#pragma warning disable CS1591
6+
7+
public static class HandlerServiceCollectionExtensions
8+
{
9+
public static IServiceCollection AddBehaviors(
10+
this IServiceCollection services)
11+
{
12+
13+
return services;
14+
}
15+
16+
public static IServiceCollection AddHandlers(
17+
this IServiceCollection services,
18+
ServiceLifetime lifetime = ServiceLifetime.Scoped
19+
)
20+
{
21+
global::Dummy.GetUsersQuery.AddHandlers(services, lifetime);
22+
23+
return services;
24+
}
25+
}

0 commit comments

Comments
 (0)