• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

net-daemon / netdaemon / 17477775006

04 Sep 2025 10:02PM UTC coverage: 83.95% (-0.1%) from 84.091%
17477775006

Pull #1326

github

web-flow
Merge c789af775 into 25a52e371
Pull Request #1326: Initial version of Func style Apps

859 of 1145 branches covered (75.02%)

Branch coverage included in aggregate %.

17 of 22 new or added lines in 4 files covered. (77.27%)

4 existing lines in 2 files now uncovered.

3362 of 3883 relevant lines covered (86.58%)

534.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/AppModel/NetDaemon.AppModel/Common/Extensions/ServiceCollectionExtension.cs
1
using System.Reflection;
2
using NetDaemon.AppModel.Internal.AppAssemblyProviders;
3
using NetDaemon.AppModel.Internal.AppFactoryProviders;
4
using NetDaemon.AppModel.Internal.Config;
5

6
namespace NetDaemon.AppModel;
7

8
/// <summary>
9
///     ServiceCollection extensions
10
/// </summary>
11
public static class ServiceCollectionExtensions
12
{
13
    /// <summary>
14
    ///     Adds a single app that gets instantiated by the provided Func
15
    /// </summary>
16
    /// <param name="services">Services</param>
17
    /// <param name="factoryFunc">The Func used to create the app</param>
18
    /// <param name="id">The id of the app. This parameter is optional,
19
    ///                  by default it tries to locate the id from the specified TAppType.</param>
20
    /// <param name="focus">Whether this app has focus or not. This parameter is optional,
21
    ///                     by default it tries to check this using the FocusAttribute</param>
22
    /// <typeparam name="TAppType">The type of the app</typeparam>
23
    public static IServiceCollection AddNetDaemonApp<TAppType>(
24
        this IServiceCollection services,
25
        Func<IServiceProvider, TAppType> factoryFunc,
26
        string? id = default,
27
        bool? focus = default) where TAppType : class
28
    {
29
        return services
7✔
30
            .AddNetDaemonAppModel()
7✔
31
            .AddSingleton(SingleAppFactoryProvider.Create(factoryFunc, id, focus));
7✔
32
    }
33

34
    /// <summary>
35
    ///     Adds a single app that runs the provided delegate when started
36
    /// </summary>
37
    /// <param name="services">Services</param>
38
    /// <param name="handler">The delegate to call when the app is started
39
    /// The delegate can have any number of arguments which will be resolved from the IServiceprovider
40
    /// if the delegate return an IDisposabe of IAsyncDisposable object, that will be disposed when the app stops
41
    /// </param>
42
    /// <param name="id">The id of the app. This parameter is optional,
43
    ///                  if not specified the app will not have an id and no input_bool will be generated for it in HA.</param>
44
    /// <param name="focus">Whether this app has focus or not. This parameter defaults to false</param>
45
    public static IServiceCollection AddNetDaemonApp(
46
        this IServiceCollection services,
47
        Delegate handler,
48
        string? id = default,
49
        bool focus = false)
50
    {
NEW
51
        return services
×
NEW
52
            .AddNetDaemonAppModel()
×
NEW
53
            .AddSingleton(SingleAppFactoryProvider.Create(handler, id, focus));
×
54
    }
55

56
    /// <summary>
57
    ///     Adds applications from the specified assembly
58
    /// </summary>
59
    /// <param name="services">Services</param>
60
    /// <param name="assembly">The assembly loading apps from</param>
61
    public static IServiceCollection AddAppsFromAssembly(this IServiceCollection services, Assembly assembly)
62
    {
63
        return services
29✔
64
            .AddNetDaemonAppModel()
29✔
65
            .AddSingleton<IAppAssemblyProvider>(new AppAssemblyProvider(assembly));
29✔
66
    }
67

68
    /// <summary>
69
    ///     Add a single app
70
    /// </summary>
71
    /// <param name="services">Services</param>
72
    /// <typeparam name="TAppType">The type of the app to add</typeparam>
73
    public static IServiceCollection AddNetDaemonApp<TAppType>(this IServiceCollection services)
74
    {
75
        return services.AddNetDaemonApp(typeof(TAppType));
6✔
76
    }
77

78
    /// <summary>
79
    ///     Add a single app
80
    /// </summary>
81
    /// <param name="services">Services</param>
82
    /// <param name="type">The type of the app to add</param>
83
    public static IServiceCollection AddNetDaemonApp(this IServiceCollection services, Type type)
84
    {
85
        return services
6✔
86
            .AddNetDaemonAppModel()
6✔
87
            .AddSingleton(SingleAppFactoryProvider.Create(type));
6✔
88
    }
89

90
    /// <summary>
91
    /// Adds the basic requirements for the NetDaemon application model
92
    /// </summary>
93
    /// <param name="services"></param>
94
    /// <returns></returns>
95
    public static IServiceCollection AddNetDaemonAppModel(this IServiceCollection services)
96
    {
97
        // Check if we already registered
98
        if (services.Any(n => n.ImplementationType == typeof(AppModelImpl)))
2,363✔
99
            return services;
3✔
100

101
        services
52✔
102
            .AddSingleton<AppModelImpl>()
52✔
103
            .AddSingleton<IAppModel>(s => s.GetRequiredService<AppModelImpl>())
27✔
104
            .AddTransient<AppModelContext>()
52✔
105
            .AddTransient<IAppModelContext>(s => s.GetRequiredService<AppModelContext>())
27✔
106
            .AddTransient<FocusFilter>()
52✔
107
            .AddScopedConfigurationBinder()
52✔
108
            .AddScopedAppServices()
52✔
109
            .AddConfigManagement()
52✔
110
            .AddAppFactoryIfNotExists();
52✔
111
        return services;
52✔
112
    }
113

114
    private static IServiceCollection AddAppFactoryIfNotExists(this IServiceCollection services)
115
    {
116
        if (services.Any(descriptor => descriptor.ImplementationType == typeof(AssemblyAppFactoryProvider)))
2,850!
117
            return services;
×
118

119
        return services
52✔
120
            .AddSingleton<AssemblyAppFactoryProvider>()
52✔
121
            .AddSingleton<IAppFactoryProvider>(provider => provider.GetRequiredService<AssemblyAppFactoryProvider>());
96✔
122
    }
123

124
    private static IServiceCollection AddScopedConfigurationBinder(this IServiceCollection services)
125
    {
126
        services
52✔
127
            .AddScoped<ConfigurationBinding>()
52✔
128
            .AddScoped<IConfigurationBinding>(s => s.GetRequiredService<ConfigurationBinding>());
66✔
129
        return services;
52✔
130
    }
131

132
    private static IServiceCollection AddScopedAppServices(this IServiceCollection services)
133
    {
134
        services
52✔
135
            .AddScoped<ApplicationScope>()
52✔
136
            .AddScoped(s => s.GetRequiredService<ApplicationScope>().ApplicationContext);
52✔
137
        return services;
52✔
138
    }
139

140
    private static IServiceCollection AddConfigManagement(this IServiceCollection services)
141
    {
142
        services.AddTransient(typeof(IAppConfig<>), typeof(AppConfig<>));
52✔
143
        return services;
52✔
144
    }
145
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc