Skip to content

Commit

Permalink
Improve Handler behavior names (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Head0nF1re authored Jan 15, 2024
1 parent 0d15dfa commit be2ee56
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,32 @@ Template template
if (pipelineBehaviors.Any(b => b is null))
return;

var typesCount = new Dictionary<string, int>()
{
["HandleBehavior"] = 1,
};

string GetVariableNameSuffix(string typeName)
{
if (!typesCount.TryGetValue(typeName, out var count))
count = 0;

typesCount[typeName] = count + 1;
return count == 0 ? string.Empty : $"{count}";
}

#pragma warning disable CA1308 // Normalize strings to uppercase
var renderBehaviors = pipelineBehaviors
.Select(b => new
{
b!.NonGenericTypeName,
VariableName = b.Name[0..1].ToLowerInvariant()
+ b.Name[1..]
+ GetVariableNameSuffix(b.Name)
})
.ToList();
#pragma warning restore CA1308 // Normalize strings to uppercase

var handlerSource = template.Render(new
{
ClassFullyQualifiedName = handler.DisplayName,
Expand All @@ -158,7 +184,7 @@ Template template
RequestType = handler.RequestType.Name,
ResponseType = handler.ResponseType.Name,

Behaviors = pipelineBehaviors,
Behaviors = renderBehaviors,
HasMsDi = hasMsDi,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ CancellationToken cancellationToken
NonGenericTypeName = constructorType,
RequestType = constraint.RequestType,
ResponseType = constraint.ResponseType,
Name = originalDefinition.Name,
};
})
.ToEquatableReadOnlyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ private sealed record Behavior
public required string NonGenericTypeName { get; init; }
public required string? RequestType { get; init; }
public required string? ResponseType { get; init; }

public required string Name { get; init; }
}

[ExcludeFromCodeCoverage]
Expand Down
41 changes: 24 additions & 17 deletions src/Immediate.Handlers.Generators/Templates/Handler.sbntxt
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,46 @@ partial class {{ class_name }}
{
public sealed class Handler : global::Immediate.Handlers.Shared.IHandler<{{ request_type }}, {{ response_type }}>
{
private readonly {{ class_fully_qualified_name }}.HandleBehavior _behavior_0;
private readonly {{ class_fully_qualified_name }}.HandleBehavior _HandleBehavior;
{{~ for behavior in (behaviors | array.reverse) ~}}
private readonly {{ behavior.non_generic_type_name }}<{{ request_type }}, {{ response_type }}> _behavior_{{for.index + 1}};
{{~ end ~}}
private readonly {{ behavior.non_generic_type_name }}<{{ request_type }}, {{ response_type }}> _{{ behavior.variable_name }};
{{~ end ~}}

public Handler(
{{ class_fully_qualified_name }}.HandleBehavior behavior_0{{ if behaviors.size > 0 }},{{ end }}
{{ class_fully_qualified_name }}.HandleBehavior HandleBehavior{{ if behaviors.size > 0 }},{{ end }}
{{~ for behavior in (behaviors | array.reverse) ~}}
{{ behavior.non_generic_type_name }}<{{ request_type }}, {{ response_type }}> behavior_{{for.index + 1}}{{ if !for.last }},{{end }}
{{ behavior.non_generic_type_name }}<{{ request_type }}, {{ response_type }}> {{ behavior.variable_name }}{{ if !for.last }},{{end }}
{{~ end ~}}
)
{
_behavior_0 = behavior_0;
_HandleBehavior = HandleBehavior;
{{~ for behavior in behaviors ~}}
_behavior_{{for.index + 1}} = behavior_{{for.index + 1}};
_{{ behavior.variable_name }} = {{ behavior.variable_name }};
{{~ end ~}}

{{~ $length = behaviors.size ~}}
{{~ if $length > 0 ~}}
{{~ for i in 1..$length ~}}
_behavior_{{ i }}.SetInnerHandler(_behavior_{{ i - 1 }});
{{~ for behavior in (behaviors | array.reverse) ~}}
{{~ if for.first ~}}
_{{ behavior.variable_name }}.SetInnerHandler(_HandleBehavior);
{{~ else ~}}
_{{ behavior.variable_name }}.SetInnerHandler(_{{ behaviors[behaviors.size - for.index].variable_name }});
{{~ end ~}}
{{~ end ~}}
}

public async global::System.Threading.Tasks.ValueTask<{{ response_type }}> HandleAsync(
{{ request_type }} request,
global::System.Threading.CancellationToken cancellationToken = default
)
{
return await _behavior_{{ $length }}
{{~ if behaviors.size > 0 ~}}
return await _{{ behaviors[0].variable_name }}
.HandleAsync(request, cancellationToken)
.ConfigureAwait(false);
{{~ else ~}}
return await _HandleBehavior
.HandleAsync(request, cancellationToken)
.ConfigureAwait(false);
{{~ end ~}}
}
}

Expand All @@ -54,7 +61,7 @@ partial class {{ class_name }}
{{~ for parameter in handler_parameters ~}}
private readonly {{ parameter.type }} _{{ parameter.name }};
{{~ end ~}}

public HandleBehavior(
{{~ for parameter in handler_parameters ~}}
{{ parameter.type }} {{ parameter.name }}{{ if !for.last }},{{ end }}
Expand All @@ -65,15 +72,15 @@ partial class {{ class_name }}
_{{ parameter.name }} = {{ parameter.name }};
{{~ end ~}}
}

public override async global::System.Threading.Tasks.ValueTask<{{ response_type }}> HandleAsync(
{{ request_type }} request,
global::System.Threading.CancellationToken cancellationToken
)
{
return await {{ class_fully_qualified_name }}
.{{ method_name }}(
request,
request,
{{~ for parameter in handler_parameters ~}}
_{{ parameter.name }},
{{~ end ~}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,42 @@ partial class GetUsersQuery
{
public sealed class Handler : global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>>
{
private readonly global::Dummy.GetUsersQuery.HandleBehavior _behavior_0;
private readonly global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _behavior_1;
private readonly global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _behavior_2;

private readonly global::Dummy.GetUsersQuery.HandleBehavior _HandleBehavior;
private readonly global::YetAnotherDummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _secondLoggingBehavior1;
private readonly global::YetAnotherDummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _loggingBehavior1;
private readonly global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _secondLoggingBehavior;
private readonly global::YetAnotherDummy.OtherBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _otherBehavior;
private readonly global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _loggingBehavior;

public Handler(
global::Dummy.GetUsersQuery.HandleBehavior behavior_0,
global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> behavior_1,
global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> behavior_2
global::Dummy.GetUsersQuery.HandleBehavior HandleBehavior,
global::YetAnotherDummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> secondLoggingBehavior1,
global::YetAnotherDummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> loggingBehavior1,
global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> secondLoggingBehavior,
global::YetAnotherDummy.OtherBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> otherBehavior,
global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> loggingBehavior
)
{
_behavior_0 = behavior_0;
_behavior_1 = behavior_1;
_behavior_2 = behavior_2;
_HandleBehavior = HandleBehavior;
_loggingBehavior = loggingBehavior;
_otherBehavior = otherBehavior;
_secondLoggingBehavior = secondLoggingBehavior;
_loggingBehavior1 = loggingBehavior1;
_secondLoggingBehavior1 = secondLoggingBehavior1;

_behavior_1.SetInnerHandler(_behavior_0);
_behavior_2.SetInnerHandler(_behavior_1);
_secondLoggingBehavior1.SetInnerHandler(_HandleBehavior);
_loggingBehavior1.SetInnerHandler(_secondLoggingBehavior1);
_secondLoggingBehavior.SetInnerHandler(_loggingBehavior1);
_otherBehavior.SetInnerHandler(_secondLoggingBehavior);
_loggingBehavior.SetInnerHandler(_otherBehavior);
}

public async global::System.Threading.Tasks.ValueTask<IEnumerable<global::Dummy.User>> HandleAsync(
global::Dummy.GetUsersQuery.Query request,
global::System.Threading.CancellationToken cancellationToken = default
)
{
return await _behavior_2
return await _loggingBehavior
.HandleAsync(request, cancellationToken)
.ConfigureAwait(false);
}
Expand All @@ -42,22 +54,22 @@ public Handler(
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>>
{
private readonly global::Dummy.UsersService _usersService;

public HandleBehavior(
global::Dummy.UsersService usersService
)
{
_usersService = usersService;
}

public override async global::System.Threading.Tasks.ValueTask<IEnumerable<global::Dummy.User>> HandleAsync(
global::Dummy.GetUsersQuery.Query request,
global::System.Threading.CancellationToken cancellationToken
)
{
return await global::Dummy.GetUsersQuery
.HandleAsync(
request,
request,
_usersService,
cancellationToken
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ public static class HandlerServiceCollectionExtensions
this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services)
{
services.AddScoped(typeof(global::Dummy.LoggingBehavior<,>));
services.AddScoped(typeof(global::YetAnotherDummy.OtherBehavior<,>));
services.AddScoped(typeof(global::Dummy.SecondLoggingBehavior<,>));
services.AddScoped(typeof(global::YetAnotherDummy.LoggingBehavior<,>));
services.AddScoped(typeof(global::YetAnotherDummy.SecondLoggingBehavior<,>));

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,42 @@ partial class GetUsersQuery
{
public sealed class Handler : global::Immediate.Handlers.Shared.IHandler<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>>
{
private readonly global::Dummy.GetUsersQuery.HandleBehavior _behavior_0;
private readonly global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _behavior_1;
private readonly global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _behavior_2;

private readonly global::Dummy.GetUsersQuery.HandleBehavior _HandleBehavior;
private readonly global::YetAnotherDummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _secondLoggingBehavior1;
private readonly global::YetAnotherDummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _loggingBehavior1;
private readonly global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _secondLoggingBehavior;
private readonly global::YetAnotherDummy.OtherBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _otherBehavior;
private readonly global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> _loggingBehavior;

public Handler(
global::Dummy.GetUsersQuery.HandleBehavior behavior_0,
global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> behavior_1,
global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> behavior_2
global::Dummy.GetUsersQuery.HandleBehavior HandleBehavior,
global::YetAnotherDummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> secondLoggingBehavior1,
global::YetAnotherDummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> loggingBehavior1,
global::Dummy.SecondLoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> secondLoggingBehavior,
global::YetAnotherDummy.OtherBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> otherBehavior,
global::Dummy.LoggingBehavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>> loggingBehavior
)
{
_behavior_0 = behavior_0;
_behavior_1 = behavior_1;
_behavior_2 = behavior_2;
_HandleBehavior = HandleBehavior;
_loggingBehavior = loggingBehavior;
_otherBehavior = otherBehavior;
_secondLoggingBehavior = secondLoggingBehavior;
_loggingBehavior1 = loggingBehavior1;
_secondLoggingBehavior1 = secondLoggingBehavior1;

_behavior_1.SetInnerHandler(_behavior_0);
_behavior_2.SetInnerHandler(_behavior_1);
_secondLoggingBehavior1.SetInnerHandler(_HandleBehavior);
_loggingBehavior1.SetInnerHandler(_secondLoggingBehavior1);
_secondLoggingBehavior.SetInnerHandler(_loggingBehavior1);
_otherBehavior.SetInnerHandler(_secondLoggingBehavior);
_loggingBehavior.SetInnerHandler(_otherBehavior);
}

public async global::System.Threading.Tasks.ValueTask<IEnumerable<global::Dummy.User>> HandleAsync(
global::Dummy.GetUsersQuery.Query request,
global::System.Threading.CancellationToken cancellationToken = default
)
{
return await _behavior_2
return await _loggingBehavior
.HandleAsync(request, cancellationToken)
.ConfigureAwait(false);
}
Expand All @@ -40,22 +52,22 @@ public Handler(
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::Dummy.GetUsersQuery.Query, IEnumerable<global::Dummy.User>>
{
private readonly global::Dummy.UsersService _usersService;

public HandleBehavior(
global::Dummy.UsersService usersService
)
{
_usersService = usersService;
}

public override async global::System.Threading.Tasks.ValueTask<IEnumerable<global::Dummy.User>> HandleAsync(
global::Dummy.GetUsersQuery.Query request,
global::System.Threading.CancellationToken cancellationToken
)
{
return await global::Dummy.GetUsersQuery
.HandleAsync(
request,
request,
_usersService,
cancellationToken
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,61 @@ public class MultipleBehaviorTest
[assembly: Behaviors(
typeof(LoggingBehavior<,>),
typeof(SecondLoggingBehavior<,>)
typeof(YetAnotherDummy.OtherBehavior<,>),
typeof(SecondLoggingBehavior<,>),
typeof(YetAnotherDummy.LoggingBehavior<,>),
typeof(YetAnotherDummy.SecondLoggingBehavior<,>)
)]
namespace YetAnotherDummy
{
public class User { }
public class UsersService
{
public Task<IEnumerable<User>> GetUsers() =>
Task.FromResult(Enumerable.Empty<User>());
}
public class OtherService
{
public Task<IEnumerable<User>> GetUsers() =>
Task.FromResult(Enumerable.Empty<User>());
}
public class OtherBehavior<TRequest, TResponse>(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
: Behavior<TRequest, TResponse>
{
public override async Task<TResponse> HandleAsync(TRequest request, CancellationToken cancellationToken)
{
var response = await Next(request, cancellationToken);
return response;
}
}
public class LoggingBehavior<TRequest, TResponse>(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
: Behavior<TRequest, TResponse>
{
public override async Task<TResponse> HandleAsync(TRequest request, CancellationToken cancellationToken)
{
var response = await Next(request, cancellationToken);
return response;
}
}
public class SecondLoggingBehavior<TRequest, TResponse>(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
: Behavior<TRequest, TResponse>
{
public override async Task<TResponse> HandleAsync(TRequest request, CancellationToken cancellationToken)
{
var response = await Next(request, cancellationToken);
return response;
}
}
}
namespace Dummy;
public class GetUsersEndpoint(GetUsersQuery.Handler handler)
Expand Down
Loading

0 comments on commit be2ee56

Please sign in to comment.