Skip to content

Commit 92ca730

Browse files
authored
Add GetInvocationContext extension methods for Hosting (#1230)
* Add GetInvocationContext extension methods for Hosting * Add tests for GetInvocationContext extensions
1 parent 4ea817d commit 92ca730

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

src/System.CommandLine.Hosting.Tests/HostingTests.cs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.Extensions.DependencyInjection;
1111
using Microsoft.Extensions.Hosting;
1212
using Microsoft.Extensions.Options;
13+
1314
using Xunit;
1415

1516
namespace System.CommandLine.Hosting.Tests
@@ -254,5 +255,116 @@ public void SubCommand(int myArgument)
254255
Service.SomeValue = myArgument;
255256
}
256257
}
258+
259+
[Fact]
260+
public static void GetInvocationContext_returns_non_null_instance()
261+
{
262+
bool ctxAsserted = false;
263+
var parser = new CommandLineBuilder()
264+
.UseHost(hostBuilder =>
265+
{
266+
InvocationContext ctx = hostBuilder.GetInvocationContext();
267+
ctx.Should().NotBeNull();
268+
ctxAsserted = true;
269+
})
270+
.Build();
271+
272+
_ = parser.Invoke(string.Empty);
273+
ctxAsserted.Should().BeTrue();
274+
}
275+
276+
[Fact]
277+
public static void GetInvocationContext_in_ConfigureServices_returns_non_null_instance()
278+
{
279+
bool ctxAsserted = false;
280+
var parser = new CommandLineBuilder()
281+
.UseHost(hostBuilder =>
282+
{
283+
hostBuilder.ConfigureServices((hostingCtx, services) =>
284+
{
285+
InvocationContext invocationCtx = hostingCtx.GetInvocationContext();
286+
invocationCtx.Should().NotBeNull();
287+
ctxAsserted = true;
288+
});
289+
})
290+
.Build();
291+
292+
_ = parser.Invoke(string.Empty);
293+
ctxAsserted.Should().BeTrue();
294+
}
295+
296+
[Fact]
297+
public static void GetInvocationContext_returns_same_instance_as_outer_middleware()
298+
{
299+
InvocationContext ctxCustom = null;
300+
InvocationContext ctxHosting = null;
301+
302+
var parser = new CommandLineBuilder()
303+
.UseMiddleware((context, next) =>
304+
{
305+
ctxCustom = context;
306+
return next(context);
307+
})
308+
.UseHost(hostBuilder =>
309+
{
310+
ctxHosting = hostBuilder.GetInvocationContext();
311+
})
312+
.Build();
313+
314+
_ = parser.Invoke(string.Empty);
315+
316+
ctxHosting.Should().BeSameAs(ctxCustom);
317+
}
318+
319+
[Fact]
320+
public static void GetInvocationContext_in_ConfigureServices_returns_same_instance_as_outer_middleware()
321+
{
322+
InvocationContext ctxCustom = null;
323+
InvocationContext ctxConfigureServices = null;
324+
325+
var parser = new CommandLineBuilder()
326+
.UseMiddleware((context, next) =>
327+
{
328+
ctxCustom = context;
329+
return next(context);
330+
})
331+
.UseHost(hostBuilder =>
332+
{
333+
hostBuilder.ConfigureServices((hostingCtx, services) =>
334+
{
335+
ctxConfigureServices = hostingCtx.GetInvocationContext();
336+
});
337+
})
338+
.Build();
339+
340+
_ = parser.Invoke(string.Empty);
341+
342+
ctxConfigureServices.Should().BeSameAs(ctxCustom);
343+
}
344+
345+
[Fact]
346+
public static void GetInvocationContext_throws_if_not_within_invocation()
347+
{
348+
var hostBuilder = new HostBuilder();
349+
hostBuilder.Invoking(b =>
350+
{
351+
_ = b.GetInvocationContext();
352+
})
353+
.Should().Throw<InvalidOperationException>();
354+
}
355+
356+
[Fact]
357+
public static void GetInvocationContext_in_ConfigureServices_throws_if_not_within_invocation()
358+
{
359+
new HostBuilder().Invoking(b =>
360+
{
361+
b.ConfigureServices((hostingCtx, services) =>
362+
{
363+
_ = hostingCtx.GetInvocationContext();
364+
});
365+
_ = b.Build();
366+
})
367+
.Should().Throw<InvalidOperationException>();
368+
}
257369
}
258370
}

src/System.CommandLine.Hosting/HostingExtensions.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,27 @@ public static IHostBuilder UseCommandHandler(this IHostBuilder builder, Type com
116116

117117
return builder;
118118
}
119+
120+
public static InvocationContext GetInvocationContext(this IHostBuilder hostBuilder)
121+
{
122+
_ = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder));
123+
124+
if (hostBuilder.Properties.TryGetValue(typeof(InvocationContext), out var ctxObj) &&
125+
ctxObj is InvocationContext invocationContext)
126+
return invocationContext;
127+
128+
throw new InvalidOperationException("Host builder has no Invocation Context registered to it.");
129+
}
130+
131+
public static InvocationContext GetInvocationContext(this HostBuilderContext context)
132+
{
133+
_ = context ?? throw new ArgumentNullException(nameof(context));
134+
135+
if (context.Properties.TryGetValue(typeof(InvocationContext), out var ctxObj) &&
136+
ctxObj is InvocationContext invocationContext)
137+
return invocationContext;
138+
139+
throw new InvalidOperationException("Host builder has no Invocation Context registered to it.");
140+
}
119141
}
120142
}

0 commit comments

Comments
 (0)