Skip to content

Commit 291c130

Browse files
middleware variable source
1 parent 3ae2be7 commit 291c130

File tree

6 files changed

+141
-2
lines changed

6 files changed

+141
-2
lines changed

src/Http/Wolverine.Http/HttpChain.Codegen.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void ICodeFile.AssembleTypes(GeneratedAssembly assembly)
5757

5858
var loggedType = determineLogMarkerType();
5959

60+
handleMethod.Sources.Add(new MiddlewareVariableSource(Middleware));
6061
handleMethod.Sources.Add(new LoggerVariableSource(loggedType));
6162
handleMethod.Sources.Add(new MessageBusSource());
6263

src/Http/WolverineWebApi/MiddlewareEndpoints.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,35 @@ public string Get(AuthenticatedRequest request)
129129
{
130130
return "All good.";
131131
}
132-
}
132+
}
133+
134+
#region sample_middleware_created_dependency
135+
136+
public class HttpMiddlewareUser
137+
{
138+
public string Name { get; set; }
139+
}
140+
141+
public class HttpServiceWithMiddlewareUser
142+
{
143+
public HttpMiddlewareUser User { get; }
144+
145+
public HttpServiceWithMiddlewareUser(HttpMiddlewareUser user) => User = user;
146+
}
147+
148+
public static class HttpMiddlewareUserCreatingMiddleware
149+
{
150+
public static HttpMiddlewareUser Before() => new() { Name = "HttpTestUser" };
151+
}
152+
153+
public class MiddlewareServiceDependencyEndpoint
154+
{
155+
[WolverineGet("/middleware/service-dependency")]
156+
public string Get(HttpServiceWithMiddlewareUser service, Recorder recorder)
157+
{
158+
recorder.Actions.Add($"Handler received Service with User: {service.User.Name}");
159+
return $"User: {service.User.Name}";
160+
}
161+
}
162+
163+
#endregion

src/Http/WolverineWebApi/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ public static async Task<int> Main(string[] args)
245245
opts.AddMiddleware(typeof(LoadTodoMiddleware),
246246
chain => chain.Method.HandlerType == typeof(UpdateEndpointWithMiddleware));
247247
opts.AddPolicy<LoadTodoPolicy>();
248+
opts.AddMiddleware(typeof(HttpMiddlewareUserCreatingMiddleware),
249+
chain => chain.Method.HandlerType == typeof(MiddlewareServiceDependencyEndpoint));
248250

249251
#region sample_user_marten_compiled_query_policy
250252

src/Testing/CoreTests/Acceptance/middleware_usage.cs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,30 @@ public async Task use_implied_middleware_that_is_inner_type()
335335
"Score touchdown"
336336
);
337337
}
338+
339+
[Fact]
340+
public async Task service_with_middleware_created_dependency_in_constructor()
341+
{
342+
var list = await invokeMessage(new MessageWithServiceDependingOnMiddlewareType(),
343+
handlers => handlers.AddMiddleware<MiddlewareUserCreatingMiddleware>());
344+
345+
list.ShouldHaveTheSameElementsAs(
346+
"MiddlewareUserCreatingMiddleware.Before - Created User: TestUser",
347+
"Handler received User: TestUser and Service with User: TestUser"
348+
);
349+
}
350+
351+
[Fact]
352+
public async Task service_only_with_middleware_created_dependency_in_constructor()
353+
{
354+
var list = await invokeMessage(new MessageWithServiceOnlyDependingOnMiddlewareType(),
355+
handlers => handlers.AddMiddleware<MiddlewareUserCreatingMiddleware>());
356+
357+
list.ShouldHaveTheSameElementsAs(
358+
"MiddlewareUserCreatingMiddleware.Before - Created User: TestUser",
359+
"Handler received Service with User: TestUser"
360+
);
361+
}
338362
}
339363

340364
public class MiddlewareActivity
@@ -671,4 +695,52 @@ public static void BackOnDefense(Recorder recorder)
671695
recorder.Actions.Add("Score touchdown");
672696
}
673697
}
674-
}
698+
}
699+
700+
#region service_with_middleware_created_dependency_in_constructor
701+
702+
public class MessageWithServiceDependingOnMiddlewareType;
703+
public class MessageWithServiceOnlyDependingOnMiddlewareType;
704+
705+
public class MiddlewareUser
706+
{
707+
public string Name { get; set; }
708+
}
709+
710+
public class ServiceWithMiddlewareUser
711+
{
712+
public MiddlewareUser User { get; }
713+
714+
public ServiceWithMiddlewareUser(MiddlewareUser user)
715+
{
716+
User = user;
717+
}
718+
}
719+
720+
public class MiddlewareUserCreatingMiddleware
721+
{
722+
public MiddlewareUser Before(Recorder recorder)
723+
{
724+
var user = new MiddlewareUser { Name = "TestUser" };
725+
recorder.Actions.Add($"MiddlewareUserCreatingMiddleware.Before - Created User: {user.Name}");
726+
return user;
727+
}
728+
}
729+
730+
public class MessageWithServiceDependingOnMiddlewareTypeHandler
731+
{
732+
public void Handle(MessageWithServiceDependingOnMiddlewareType message, MiddlewareUser user, ServiceWithMiddlewareUser service, Recorder recorder)
733+
{
734+
recorder.Actions.Add($"Handler received User: {user.Name} and Service with User: {service.User.Name}");
735+
}
736+
}
737+
738+
public class MessageWithServiceOnlyDependingOnMiddlewareTypeHandler
739+
{
740+
public void Handle(MessageWithServiceOnlyDependingOnMiddlewareType message, ServiceWithMiddlewareUser service, Recorder recorder)
741+
{
742+
recorder.Actions.Add($"Handler received Service with User: {service.User.Name}");
743+
}
744+
}
745+
746+
#endregion

src/Wolverine/Runtime/Handlers/HandlerChain.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ void ICodeFile.AssembleTypes(GeneratedAssembly assembly)
211211

212212
var handleMethod = _generatedType.MethodFor(nameof(MessageHandler.HandleAsync));
213213

214+
handleMethod.Sources.Add(new MiddlewareVariableSource(Middleware));
214215
handleMethod.Sources.Add(new LoggerVariableSource(MessageType));
215216
var envelopeVariable = new Variable(typeof(Envelope),
216217
$"context.{nameof(IMessageContext.Envelope)}");
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using JasperFx.CodeGeneration.Frames;
2+
using JasperFx.CodeGeneration.Model;
3+
4+
namespace Wolverine.Runtime.Handlers;
5+
6+
/// <summary>
7+
/// Variable source that provides variables created by middleware frames
8+
/// so they can be found during service dependency resolution.
9+
/// This enables services with constructor dependencies on middleware-created types
10+
/// to be properly resolved.
11+
/// </summary>
12+
public class MiddlewareVariableSource : IVariableSource
13+
{
14+
private readonly IReadOnlyList<Variable> _middlewareVariables;
15+
16+
public MiddlewareVariableSource(IEnumerable<Frame> middlewareFrames)
17+
{
18+
_middlewareVariables = middlewareFrames
19+
.SelectMany(f => f.Creates)
20+
.ToList();
21+
}
22+
23+
public bool Matches(Type type)
24+
{
25+
return _middlewareVariables.Any(v => v.VariableType == type);
26+
}
27+
28+
public Variable Create(Type type)
29+
{
30+
return _middlewareVariables.First(v => v.VariableType == type);
31+
}
32+
}

0 commit comments

Comments
 (0)