Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,16 @@ public async Task TestApplicationContextIsDisposedMultipleTimesNotThrowsExceptio
await applicationContext.DisposeAsync();
await applicationContext.DisposeAsync();
}

[Fact]
public void TestApplicationContextExposesAppFactoryIdAsCurrentApp()
{
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var appFactory = new Mock<IAppFactory>();
appFactory.SetupGet(f => f.Id).Returns("MyApps.SomeApp");

ICurrentApp currentApp = new ApplicationContext(serviceProvider, appFactory.Object);

currentApp.Id.Should().Be("MyApps.SomeApp");
}
}
36 changes: 36 additions & 0 deletions src/AppModel/NetDaemon.AppModel.Tests/Context/CurrentAppTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using NetDaemon.AppModel.Internal;

namespace NetDaemon.AppModel.Tests.Context;

public class CurrentAppTests
{
[Fact]
public async Task AppCanInjectCurrentAppAndGetsItsOwnId()
{
// ARRANGE
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddNetDaemonApp<AppThatCapturesItsId>();

var serviceProvider = serviceCollection.BuildServiceProvider();
var appModelContext = serviceProvider.GetRequiredService<IAppModelContext>();

// ACT
await appModelContext.InitializeAsync(CancellationToken.None);

// ASSERT
var application = (Application)appModelContext.Applications.Single();
var instance = (AppThatCapturesItsId)application.ApplicationContext!.Instance!;
instance.CapturedId.Should().Be(typeof(AppThatCapturesItsId).FullName);
}

private sealed class AppThatCapturesItsId
{
public AppThatCapturesItsId(ICurrentApp currentApp)
{
CapturedId = currentApp.Id;
}

public string CapturedId { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ private static IServiceCollection AddScopedAppServices(this IServiceCollection s
{
services
.AddScoped<ApplicationScope>()
.AddScoped(s => s.GetRequiredService<ApplicationScope>().ApplicationContext);
.AddScoped(s => s.GetRequiredService<ApplicationScope>().ApplicationContext)
.AddScoped<ICurrentApp>(s => s.GetRequiredService<ApplicationContext>());
return services;
}

Expand Down
19 changes: 19 additions & 0 deletions src/AppModel/NetDaemon.AppModel/Common/ICurrentApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace NetDaemon.AppModel;

/// <summary>
/// Provides information about the app that owns the current dependency injection scope.
/// </summary>
/// <remarks>
/// Resolve this from an app's constructor, or from any service registered in the app's
/// scope, to discover which app is being instantiated - for example to select per-app
/// configuration or logging.
/// </remarks>
public interface ICurrentApp
{
/// <summary>
/// Gets the unique id of the app that owns the current scope. This is the same id
/// NetDaemon uses elsewhere: the value of <see cref="NetDaemonAppAttribute.Id"/> when
/// set, otherwise the full name of the app type.
/// </summary>
string Id { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace NetDaemon.AppModel.Internal;

internal sealed class ApplicationContext : IAsyncDisposable
internal sealed class ApplicationContext : IAsyncDisposable, ICurrentApp
{
private readonly CancellationTokenSource _cancelTokenSource = new();
private readonly IServiceScope? _serviceScope;
Expand All @@ -21,9 +21,13 @@ public ApplicationContext(IServiceProvider serviceProvider, IAppFactory appFacto
if (appScope != null) appScope.ApplicationContext = this;

// Now create the actual app from the new scope
Id = appFactory.Id;
Instance = appFactory.Create(scopedProvider);
}

/// <inheritdoc />
public string Id { get; }

public object? Instance { get; private set; }

public async Task InitializeAsync()
Expand Down
Loading