Skip to content

Commit 646cc3b

Browse files
committed
fix(SimpleW.Helper.DependencyInjection): exception when delegate return Task/ValueTask with object (#382)
1 parent 42213e5 commit 646cc3b

2 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/SimpleW.Helper.DependencyInjection/DependencyInjectionRouteExecutorFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ private static ReturnAdapter CreateReturnAdapter(Type returnType) {
282282

283283
private static ReturnAdapter CreateClosedReturnAdapter(MethodInfo openGenericMethod, Type resultType) {
284284
MethodInfo closedMethod = openGenericMethod.MakeGenericMethod(resultType);
285-
return (ReturnAdapter)Delegate.CreateDelegate(typeof(ReturnAdapter), closedMethod);
285+
Func<ReturnAdapter> factory = (Func<ReturnAdapter>)Delegate.CreateDelegate(typeof(Func<ReturnAdapter>), closedMethod);
286+
return factory();
286287
}
287288

288289
private static ReturnAdapter CreateTaskWithResultAdapter<T>() {

src/test/DependencyInjectionTests.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,62 @@ public async Task MapControllers_Should_Discover_Controllers_From_Base_Type_When
178178
}
179179
}
180180

181+
[Fact]
182+
public async Task MapController_Should_Support_Task_With_Result_When_Di_Is_Enabled() {
183+
int port = PortManager.GetFreePort();
184+
185+
await using ServiceProvider rootProvider = new ServiceCollection()
186+
.AddScoped<AsyncResultMessageService>(_ => new AsyncResultMessageService("task"))
187+
.BuildServiceProvider();
188+
189+
var server = new SimpleWServer(IPAddress.Loopback, port);
190+
server.UseDependencyInjection(rootProvider);
191+
server.MapController<TaskResultDiController>("/api");
192+
193+
try {
194+
await server.StartAsync();
195+
196+
var client = new HttpClient();
197+
var response = await client.GetAsync($"http://{server.Address}:{server.Port}/api/async-result/task");
198+
var content = await response.Content.ReadAsStringAsync();
199+
200+
Check.That(response.StatusCode).Is(HttpStatusCode.OK);
201+
Check.That(content).IsEqualTo(JsonSerializer.Serialize(new { message = "task" }));
202+
}
203+
finally {
204+
await server.StopAsync();
205+
PortManager.ReleasePort(port);
206+
}
207+
}
208+
209+
[Fact]
210+
public async Task MapController_Should_Support_ValueTask_With_Result_When_Di_Is_Enabled() {
211+
int port = PortManager.GetFreePort();
212+
213+
await using ServiceProvider rootProvider = new ServiceCollection()
214+
.AddScoped<AsyncResultMessageService>(_ => new AsyncResultMessageService("value-task"))
215+
.BuildServiceProvider();
216+
217+
var server = new SimpleWServer(IPAddress.Loopback, port);
218+
server.UseDependencyInjection(rootProvider);
219+
server.MapController<ValueTaskResultDiController>("/api");
220+
221+
try {
222+
await server.StartAsync();
223+
224+
var client = new HttpClient();
225+
var response = await client.GetAsync($"http://{server.Address}:{server.Port}/api/async-result/value-task");
226+
var content = await response.Content.ReadAsStringAsync();
227+
228+
Check.That(response.StatusCode).Is(HttpStatusCode.OK);
229+
Check.That(content).IsEqualTo(JsonSerializer.Serialize(new { message = "value-task" }));
230+
}
231+
finally {
232+
await server.StopAsync();
233+
PortManager.ReleasePort(port);
234+
}
235+
}
236+
181237
[Fact]
182238
public async Task MapController_Should_Dispose_Controller_After_Request_When_Di_Is_Enabled() {
183239
int port = PortManager.GetFreePort();
@@ -364,6 +420,52 @@ public object Ping() {
364420

365421
}
366422

423+
public sealed class AsyncResultMessageService {
424+
425+
public string Message { get; }
426+
427+
public AsyncResultMessageService(string message) {
428+
Message = message;
429+
}
430+
431+
}
432+
433+
[Route("/async-result")]
434+
public sealed class TaskResultDiController : Controller {
435+
436+
private readonly AsyncResultMessageService _messageService;
437+
438+
public TaskResultDiController(AsyncResultMessageService messageService) {
439+
_messageService = messageService;
440+
}
441+
442+
[Route("GET", "/task")]
443+
public Task<object> Get() {
444+
return Task.FromResult<object>(new {
445+
message = _messageService.Message
446+
});
447+
}
448+
449+
}
450+
451+
[Route("/async-result")]
452+
public sealed class ValueTaskResultDiController : Controller {
453+
454+
private readonly AsyncResultMessageService _messageService;
455+
456+
public ValueTaskResultDiController(AsyncResultMessageService messageService) {
457+
_messageService = messageService;
458+
}
459+
460+
[Route("GET", "/value-task")]
461+
public ValueTask<object> Get() {
462+
return ValueTask.FromResult<object>(new {
463+
message = _messageService.Message
464+
});
465+
}
466+
467+
}
468+
367469
[Route("/dispose")]
368470
public sealed class DisposableDiController : Controller, IDisposable {
369471

0 commit comments

Comments
 (0)