This commit is contained in:
bytewizer 2022-07-09 21:00:12 -07:00
Родитель c301e32634
Коммит ae9c981058
40 изменённых файлов: 590 добавлений и 876 удалений

Просмотреть файл

@ -10,7 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Hosting", "nanoFramework.Hosting\nanoFramework.Hosting.nfproj", "{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection", "..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj", "{A2B2222C-0553-4877-8CF1-4458B30C0081}"
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Hosting.UnitTests", "tests\nanoFramework.Hosting.UnitTests.nfproj", "{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -24,12 +24,12 @@ Global
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Build.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Build.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Deploy.0 = Release|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Release|Any CPU.Build.0 = Release|Any CPU
{450AF2B8-2C40-4C3D-BEE3-091F01BD97F1}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -14,7 +14,11 @@ namespace nanoFramework.Hosting
public abstract class BackgroundService : IHostedService, IDisposable
{
private Thread _executeThread;
private CancellationTokenSource _stoppingCts;
/// <summary>
/// Gets whether cancellation has been requested for this service.
/// </summary>
protected bool CancellationRequested { get; private set; } = false;
/// <summary>
/// Gets the <see cref="Thread"/> that executes the background operation.
@ -28,45 +32,35 @@ namespace nanoFramework.Hosting
/// This method is called when the <see cref="IHostedService"/> starts. The implementation should return a thread that represents
/// the lifetime of the long running operation(s) being performed.
/// </summary>
protected abstract void ExecuteAsync(CancellationToken stoppingToken);
protected abstract void ExecuteAsync();
/// <inheritdoc />
public virtual void StartAsync()
public virtual void Start()
{
_stoppingCts = new CancellationTokenSource();
// Store the thread we're executing
_executeThread = new Thread(() =>
{
ExecuteAsync(_stoppingCts.Token);
ExecuteAsync();
});
}
/// <inheritdoc />
public virtual void StopAsync()
public virtual void Stop()
{
if (_executeThread == null)
{
return;
}
try
{
// Signal cancellation to the executing method
_stoppingCts!.Cancel();
}
finally
{
// Wait for thread to exit
_executeThread.Join();
_executeThread = null;
}
// Signal cancellation to the executing method
CancellationRequested = true;
// Wait for thread to exit
_executeThread.Join();
_executeThread = null;
}
/// <inheritdoc />
public virtual void Dispose()
{
_stoppingCts?.Dispose();
}
public virtual void Dispose() { }
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using System;
namespace nanoFramework.Hosting
{
public class ExecutingContext
{
/// <summary>
/// Gets whether cancellation has been requested for this service.
/// </summary>
public bool IsCancellationRequested { get; set; } = false;
public Exception Exception { get; set; }
}
}

Просмотреть файл

@ -5,6 +5,7 @@
using System;
using System.Collections;
using System.Diagnostics;
using nanoFramework.DependencyInjection;
@ -18,12 +19,33 @@ namespace nanoFramework.Hosting
private bool _hostBuilt;
private IServiceProvider _appServices;
private HostBuilderContext _hostBuilderContext;
private ServiceProviderOptions _providerOptions;
private readonly ArrayList _configureServicesActions = new ArrayList();
private readonly ServiceProviderOptions _providerOptions;
private readonly ArrayList _configureServicesActions;
/// <summary>
/// Initializes a new instance of <see cref="HostBuilder"/>.
/// </summary>
public HostBuilder()
{
_configureServicesActions = new ArrayList();
if (Debugger.IsAttached)
{
// enables validation as default when debugger is attached
_providerOptions = new ServiceProviderOptions()
{
ValidateOnBuild = true
};
}
else
{
_providerOptions = new ServiceProviderOptions();
}
}
/// <inheritdoc />
public object[] Properties { get; } = new object[0];
public object[] Properties { get; set; } = new object[0];
/// <inheritdoc />
public IHostBuilder ConfigureServices(ServiceContextDelegate configureDelegate)
@ -41,8 +63,8 @@ namespace nanoFramework.Hosting
/// <inheritdoc />
public IHostBuilder UseDefaultServiceProvider(ProviderContextDelegate configureDelegate)
{
_providerOptions = new ServiceProviderOptions();
configureDelegate(_hostBuilderContext, _providerOptions);
return this;
}
@ -69,14 +91,7 @@ namespace nanoFramework.Hosting
configureServicesAction(_hostBuilderContext, services);
}
if (_providerOptions == null)
{
_appServices = services.BuildServiceProvider();
}
else
{
_appServices = services.BuildServiceProvider(_providerOptions);
}
_appServices = services.BuildServiceProvider(_providerOptions);
if (_appServices == null)
{

Просмотреть файл

@ -4,6 +4,7 @@
//
using System;
using nanoFramework.DependencyInjection;
namespace nanoFramework.Hosting

Просмотреть файл

@ -17,7 +17,7 @@ namespace nanoFramework.Hosting
/// <summary>
/// A central location for sharing state between components during the host building process.
/// </summary>
object[] Properties { get; }
object[] Properties { get; set; }
/// <summary>
/// Adds services to the container. This can be called multiple times and the results will be additive.

Просмотреть файл

@ -13,11 +13,11 @@ namespace nanoFramework.Hosting
/// <summary>
/// Triggered when the application host is ready to start the service.
/// </summary>
void StartAsync();
void Start();
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// </summary>
void StopAsync();
void Stop();
}
}

Просмотреть файл

@ -38,7 +38,7 @@ namespace nanoFramework.Hosting.Internal
try
{
// TODO: Thead exceptions are not passed back to main thread. What to do?
hostedService.StartAsync();
hostedService.Start();
if (hostedService is BackgroundService backgroundService)
{
@ -61,12 +61,17 @@ namespace nanoFramework.Hosting.Internal
/// <inheritdoc />
public void Stop()
{
if (_hostedServices == null)
{
return;
}
ArrayList exceptions = null;
foreach (IHostedService hostedService in _hostedServices)
{
try
{
hostedService.StopAsync();
hostedService.Stop();
}
catch (Exception ex)
{

Просмотреть файл

@ -61,7 +61,7 @@ namespace nanoFramework.Hosting
protected abstract void ExecuteAsync(object state);
/// <inheritdoc />
public virtual void StartAsync()
public virtual void Start()
{
_executeTimer = new Timer(state =>
{
@ -70,7 +70,7 @@ namespace nanoFramework.Hosting
}
/// <inheritdoc />
public virtual void StopAsync()
public virtual void Stop()
{
if (_executeTimer == null)
{

Просмотреть файл

@ -18,6 +18,7 @@
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Hosting\ExecutingContext.cs" />
<Compile Include="Hosting\SchedulerService.cs" />
<Compile Include="Hosting\BackgroundService.cs" />
<Compile Include="Hosting\Host.cs" />
@ -40,16 +41,13 @@
<Reference Include="mscorlib">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="System.Threading">
<HintPath>..\packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll</HintPath>
<Reference Include="nanoFramework.DependencyInjection">
<HintPath>..\packages\nanoFramework.DependencyInjection.1.0.0.11\lib\nanoFramework.DependencyInjection.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>

Просмотреть файл

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Threading" version="1.0.4" targetFramework="netnano1.0" />
<package id="nanoFramework.DependencyInjection" version="1.0.0.11" targetFramework="netnano1.0" />
</packages>

Просмотреть файл

@ -1,43 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32519.379
MinimumVisualStudioVersion = 10.0.40219.1
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "SensorQueue", "SensorQueue.nfproj", "{9E9DC577-4DA0-4D2D-B504-3054A7F19054}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Hosting", "..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj", "{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection", "..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj", "{A2B2222C-0553-4877-8CF1-4458B30C0081}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.Build.0 = Release|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.Deploy.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Build.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Build.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC40AA7-C769-4EBB-9C18-8CE1692239EB}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,28 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using nanoFramework.Hosting;
using nanoFramework.DependencyInjection;
namespace Hosting
{
public class Program
{
public static void Main()
{
CreateHostBuilder().Build().Run();
}
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton(typeof(BackgroundQueue));
services.AddHostedService(typeof(SensorService));
services.AddHostedService(typeof(DisplayService));
services.AddHostedService(typeof(MonitorService));
});
}
}

Просмотреть файл

@ -1,33 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Hosting")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Hosting")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>{9E9DC577-4DA0-4D2D-B504-3054A7F19054}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>DependencyInjection</RootNamespace>
<AssemblyName>DependencyInjection</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Services\SensorService.cs" />
<Compile Include="Services\BackgroundQueue.cs" />
<Compile Include="Services\DisplayService.cs" />
<Compile Include="Services\MonitorService.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.System.Collections">
<HintPath>packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll</HintPath>
</Reference>
<Reference Include="System.Threading">
<HintPath>packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj" />
<ProjectReference Include="..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -1,58 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System;
using System.Collections;
namespace Hosting
{
internal class BackgroundQueue
{
private readonly int _maxQueueCount = 500;
private readonly Queue _items = new Queue();
private readonly object _syncLock = new object();
public int QueueCount
{
get
{
return _items.Count;
}
}
public void Enqueue(object item)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
if (_items.Count < _maxQueueCount)
{
lock (_syncLock)
{
_items.Enqueue(item);
}
}
}
public object Dequeue()
{
if (_items.Count > 0)
{
lock (_syncLock)
{
var workItem = _items.Dequeue();
if (workItem != null)
{
return workItem;
}
}
}
return null;
}
}
}

Просмотреть файл

@ -1,54 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System;
using System.Threading;
using System.Diagnostics;
using nanoFramework.Hosting;
namespace Hosting
{
internal class DisplayService : BackgroundService
{
private readonly BackgroundQueue _queue;
public DisplayService(BackgroundQueue queue)
{
_queue = queue;
}
protected override void ExecuteAsync(CancellationToken cancellationToken)
{
Debug.WriteLine($"Service '{nameof(DisplayService)}' is now running in the background.");
cancellationToken.Register(() => Debug.WriteLine($"Service '{nameof(DisplayService)}' is stopping."));
while (!cancellationToken.IsCancellationRequested)
{
try
{
Thread.Sleep(50);
var workItem = _queue.Dequeue();
if (workItem == null)
{
continue;
}
FakeDisplay(workItem.ToString());
}
catch (Exception ex)
{
Debug.WriteLine($"An error occurred when dequeueing work item. Exception: {ex}");
}
}
}
void FakeDisplay(string text)
{
//Debug.WriteLine(text);
}
}
}

Просмотреть файл

@ -1,42 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System;
using System.Diagnostics;
using nanoFramework.Hosting;
namespace Hosting
{
internal class MonitorService : SchedulerService
{
private readonly BackgroundQueue _queue;
public MonitorService(BackgroundQueue queue)
: base(TimeSpan.FromSeconds(1))
{
_queue = queue;
}
public override void StartAsync()
{
Debug.WriteLine($"Service '{nameof(MonitorService)}' is now running in the background.");
base.StartAsync();
}
protected override void ExecuteAsync(object state)
{
Debug.WriteLine($"Queue Depth: {_queue.QueueCount}");
}
public override void StopAsync()
{
Debug.WriteLine($"Service '{nameof(MonitorService)}' is stopping.");
base.StopAsync();
}
}
}

Просмотреть файл

@ -1,51 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System;
using System.Threading;
using System.Diagnostics;
using nanoFramework.Hosting;
namespace Hosting
{
internal class SensorService : BackgroundService
{
private readonly Random _random;
private readonly BackgroundQueue _queue;
public SensorService(BackgroundQueue queue)
{
_queue = queue;
_random = new Random();
}
protected override void ExecuteAsync(CancellationToken cancellationToken)
{
Debug.WriteLine($"Service '{nameof(SensorService)}' is now running in the background.");
cancellationToken.Register(() => Debug.WriteLine($"Service '{nameof(SensorService)}' is stopping."));
while (!cancellationToken.IsCancellationRequested)
{
try
{
Thread.Sleep(1);
var workItem = FakeSensor();
_queue.Enqueue(workItem);
}
catch (Exception ex)
{
Debug.WriteLine($"An error occurred when enqueueing work item. Exception: {ex}");
}
}
}
private int FakeSensor()
{
Thread.Sleep(_random.Next(100));
return _random.Next(1000);
}
}
}

Просмотреть файл

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Collections" version="1.4.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Threading" version="1.0.4" targetFramework="netnano1.0" />
</packages>

Просмотреть файл

@ -1,43 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32519.379
MinimumVisualStudioVersion = 10.0.40219.1
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection", "..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj", "{A2B2222C-0553-4877-8CF1-4458B30C0081}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Hosting", "..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj", "{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Simple", "Simple.nfproj", "{D8BCA7F1-0FEA-4C41-98C0-29502752831E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Build.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Deploy.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Build.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Release|Any CPU.Build.0 = Release|Any CPU
{D8BCA7F1-0FEA-4C41-98C0-29502752831E}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC40AA7-C769-4EBB-9C18-8CE1692239EB}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,102 +0,0 @@
using System;
using System.Threading;
using System.Device.Gpio;
using System.Diagnostics;
using nanoFramework.Hosting;
using nanoFramework.DependencyInjection;
namespace Hosting
{
public class Program
{
public static void Main()
{
CreateHostBuilder().Build().Run();
}
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton(typeof(HardwareService));
services.AddHostedService(typeof(LedHostedService));
services.AddHostedService(typeof(TimedHostedService));
});
}
internal class HardwareService : IDisposable
{
public GpioController GpioController { get; private set; }
public HardwareService()
{
GpioController = new GpioController();
}
public void Dispose()
{
GpioController.Dispose();
}
}
internal class LedHostedService : BackgroundService
{
private readonly HardwareService _hardware;
public LedHostedService(HardwareService hardware)
{
_hardware = hardware;
}
protected override void ExecuteAsync(CancellationToken cancellationToken)
{
Debug.WriteLine("LED Hosted Service running.");
cancellationToken.Register(() => Debug.WriteLine("LED Hosted Service is stopping."));
var ledPin = 16; //LD1;
GpioPin led = _hardware.GpioController.OpenPin(ledPin, PinMode.Output);
while (!cancellationToken.IsCancellationRequested)
{
led.Toggle();
Thread.Sleep(100);
}
}
}
internal class TimedHostedService : IHostedService, IDisposable
{
private Timer _timer = null;
private int executionCount = 0;
public void StartAsync()
{
Debug.WriteLine("Timed Hosted Service running.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
}
private void DoWork(object state)
{
var count = Interlocked.Increment(ref executionCount);
Debug.WriteLine($"Timed Hosted Service is working. Count: {count}");
}
public void StopAsync()
{
Debug.WriteLine("Timed Hosted Service is stopping.");
_timer.Change(Timeout.Infinite, 0);
}
public void Dispose()
{
_timer.Dispose();
}
}
}

Просмотреть файл

@ -1,33 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharp.BlankApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharp.BlankApplication")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>d8bca7f1-0fea-4c41-98c0-29502752831e</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>Sample2</RootNamespace>
<AssemblyName>Sample2</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.Runtime.Events">
<HintPath>packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll</HintPath>
</Reference>
<Reference Include="System.Device.Gpio">
<HintPath>packages\nanoFramework.System.Device.Gpio.1.0.4\lib\System.Device.Gpio.dll</HintPath>
</Reference>
<Reference Include="System.Threading">
<HintPath>packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj" />
<ProjectReference Include="..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
<package id="nanoFramework.Runtime.Events" version="1.10.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Device.Gpio" version="1.0.4" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Threading" version="1.0.4" targetFramework="netnano1.0" />
</packages>

Просмотреть файл

@ -1,43 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32519.379
MinimumVisualStudioVersion = 10.0.40219.1
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "SlowBlink", "SlowBlink.nfproj", "{9E9DC577-4DA0-4D2D-B504-3054A7F19054}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.DependencyInjection", "..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj", "{A2B2222C-0553-4877-8CF1-4458B30C0081}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Hosting", "..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj", "{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.Build.0 = Release|Any CPU
{9E9DC577-4DA0-4D2D-B504-3054A7F19054}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Build.0 = Release|Any CPU
{A2B2222C-0553-4877-8CF1-4458B30C0081}.Release|Any CPU.Deploy.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Build.0 = Release|Any CPU
{AEEA2C38-FF56-4ACD-9DF5-E0BEA2D1263A}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1EC40AA7-C769-4EBB-9C18-8CE1692239EB}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,28 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using nanoFramework.Hosting;
using nanoFramework.DependencyInjection;
namespace Hosting
{
public class Program
{
public static void Main()
{
var hostBuilder = CreateHostBuilder();
var host = hostBuilder.Build();
host.Run();
}
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton(typeof(IHardwareService), typeof(HardwareService));
services.AddHostedService(typeof(LedService));
});
}
}

Просмотреть файл

@ -1,27 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System;
using System.Device.Gpio;
namespace Hosting
{
internal class HardwareService : IHardwareService, IDisposable
{
private readonly GpioController _gpioController;
public HardwareService()
{
_gpioController = new GpioController();
}
public GpioController GpioController { get { return _gpioController; } }
public void Dispose()
{
_gpioController.Dispose();
}
}
}

Просмотреть файл

@ -1,14 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System.Device.Gpio;
namespace Hosting
{
public interface IHardwareService
{
GpioController GpioController { get; }
}
}

Просмотреть файл

@ -1,35 +0,0 @@
//
// Copyright (c) .NET Foundation and Contributors
// See LICENSE file in the project root for full license information.
//
using System.Threading;
using System.Device.Gpio;
using nanoFramework.Hosting;
namespace Hosting
{
internal class LedService : BackgroundService
{
private readonly IHardwareService _hardware;
public LedService(IHardwareService hardware)
{
_hardware = hardware;
}
protected override void ExecuteAsync(CancellationToken cancellationToken)
{
var ledPin = 16;
GpioPin led = _hardware.GpioController.OpenPin(ledPin, PinMode.Output);
while (!cancellationToken.IsCancellationRequested)
{
led.Toggle();
Thread.Sleep(1000);
}
}
}
}

Просмотреть файл

@ -1,60 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>{9E9DC577-4DA0-4D2D-B504-3054A7F19054}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>DependencyInjection</RootNamespace>
<AssemblyName>DependencyInjection</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Services\HardwareService.cs" />
<Compile Include="Services\IHardwareService.cs" />
<Compile Include="Services\LedService.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.Logging">
<HintPath>packages\nanoFramework.Logging.1.0.1.29\lib\nanoFramework.Logging.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.Runtime.Events">
<HintPath>packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.System.Collections">
<HintPath>packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll</HintPath>
</Reference>
<Reference Include="System.Device.Gpio">
<HintPath>packages\nanoFramework.System.Device.Gpio.1.0.4\lib\System.Device.Gpio.dll</HintPath>
</Reference>
<Reference Include="System.Threading">
<HintPath>packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection\nanoFramework.DependencyInjection.nfproj" />
<ProjectReference Include="..\..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
<package id="nanoFramework.Logging" version="1.0.1.29" targetFramework="netnano1.0" />
<package id="nanoFramework.Runtime.Events" version="1.10.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Collections" version="1.4.0" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Device.Gpio" version="1.0.4" targetFramework="netnano1.0" />
<package id="nanoFramework.System.Threading" version="1.0.4" targetFramework="netnano1.0" />
</packages>

Просмотреть файл

@ -0,0 +1,105 @@
using System;
using System.Threading;
using nanoFramework.TestFramework;
namespace nanoFramework.Hosting.UnitTests
{
[TestClass]
public class BackgroundServiceTests
{
[TestMethod]
public void StartStopAndDisposeBackgroundService()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(FakeBackgroundService));
}).Build();
var service = (FakeBackgroundService)host.Services.GetService(typeof(IHostedService));
Assert.NotNull(service);
host.Start();
Assert.True(service.IsStarted);
Thread.Sleep(10);
Assert.True(service.IsCompleted);
host.Stop();
Assert.True(service.IsStopped);
host.Dispose();
}
[TestMethod]
public void StartStopBackgroundServiceThrowsAggregateException()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(ExecptionBackgroundService));
}).Build();
Assert.Throws(typeof(AggregateException),
() => host.Start());
Assert.Throws(typeof(AggregateException),
() => host.Stop());
}
}
public class FakeBackgroundService : BackgroundService
{
public bool IsStarted { get; set; }
public bool IsCompleted { get; set; }
public bool IsStopped { get; set; }
public override void Start()
{
IsStarted = true;
base.Start();
}
protected override void ExecuteAsync()
{
IsCompleted = true;
while (!CancellationRequested)
{
Thread.Sleep(10);
}
}
public override void Stop()
{
IsStopped = true;
base.Stop();
}
}
public class ExecptionBackgroundService : BackgroundService
{
public override void Start()
{
base.Start();
throw new NotImplementedException();
}
protected override void ExecuteAsync()
{
throw new NotImplementedException();
}
public override void Stop()
{
base.Stop();
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,99 @@
using System;
using nanoFramework.TestFramework;
namespace nanoFramework.Hosting.UnitTests
{
[TestClass]
public class HostedServiceTests
{
[TestMethod]
public void StartStopHostedService()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(FakeHostedService));
}).Build();
var service = (FakeHostedService)host.Services.GetService(typeof(IHostedService));
Assert.NotNull(service);
host.Start();
Assert.True(service.IsStarted);
host.Stop();
Assert.True(service.IsStopped);
}
[TestMethod]
public void StartStopHostedServiceThrowsAggregateException()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(ExceptionHostedService));
}).Build();
Assert.Throws(typeof(AggregateException),
() => host.Start());
Assert.Throws(typeof(AggregateException),
() => host.Stop());
}
[TestMethod]
public void StopWithoutStartNoops()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(FakeHostedService));
}).Build();
host.Stop();
}
[TestMethod]
public void StartWhenAlreadyStartedNoops()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(FakeHostedService));
}).Build();
host.Start();
host.Start();
}
}
public class FakeHostedService : IHostedService
{
public bool IsStarted { get; set; } = false;
public bool IsStopped { get; set; } = false;
public void Start()
{
IsStarted = true;
}
public void Stop()
{
IsStopped = true;
}
}
public class ExceptionHostedService : IHostedService
{
public void Start()
{
throw new NotImplementedException();
}
public void Stop()
{
throw new NotImplementedException();
}
}
}

100
tests/HostingTests.cs Normal file
Просмотреть файл

@ -0,0 +1,100 @@
using System;
using nanoFramework.TestFramework;
using nanoFramework.DependencyInjection;
namespace nanoFramework.Hosting.UnitTests
{
[TestClass]
public class HostingTests
{
[TestMethod]
public void BuildAndDispose()
{
using IHost host = new HostBuilder().Build();
}
[TestMethod]
public void StopWithoutCancellation()
{
var builder = new HostBuilder();
using (var host = builder.Build())
{
host.Start();
host.Stop();
}
}
[TestMethod]
public void DefaultServicesAreAvailable()
{
using (var host = new HostBuilder()
.Build())
{
Assert.NotNull(host.Services.GetRequiredService(typeof(IHost)));
Assert.NotNull(host.Services.GetRequiredService(typeof(IHostBuilder)));
Assert.NotNull(host.Services.GetRequiredService(typeof(IServiceProvider)));
}
}
[TestMethod]
public void BuildDoesNotAllowBuildingMuiltipleTimes()
{
HostBuilder builder = new HostBuilder();
using (builder.Build())
{
Assert.Throws(typeof(InvalidOperationException),() => builder.Build());
}
}
[TestMethod]
public void ConfigureServicesCanBeCalledMultipleTimes()
{
var callCount = 0; // Verify ordering
var hostBuilder = new HostBuilder()
.ConfigureServices((services) =>
{
Assert.Equal(0, callCount++);
services.AddTransient(typeof(ServiceA), typeof(ServiceA));
})
.ConfigureServices((services) =>
{
Assert.Equal(1, callCount++);
services.AddTransient(typeof(ServiceB), typeof(ServiceB));
});
using (var host = hostBuilder.Build())
{
Assert.Equal(2, callCount);
Assert.NotNull(host.Services.GetRequiredService(typeof(ServiceA)));
Assert.NotNull(host.Services.GetRequiredService(typeof(ServiceB)));
}
}
[TestMethod]
public void BuilderPropertiesAreAvailableInBuilderAndContext()
{
var hostBuilder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
Assert.Equal("value0", (string)hostContext.Properties[0]);
Assert.Equal("value1", (string)hostContext.Properties[1]);
});
hostBuilder.Properties = new object[2];
hostBuilder.Properties[0] = "value0";
hostBuilder.Properties[1] = "value1";
Assert.Equal("value0", (string)hostBuilder.Properties[0]);
Assert.Equal("value1", (string)hostBuilder.Properties[1]);
using (hostBuilder.Build()) { }
}
}
public class ServiceA { }
public class ServiceB { }
}

Просмотреть файл

@ -5,12 +5,10 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Hosting")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Hosting")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Просмотреть файл

@ -0,0 +1,109 @@
using System;
using System.Threading;
using nanoFramework.TestFramework;
namespace nanoFramework.Hosting.UnitTests
{
[TestClass]
public class SchedulerServiceTests
{
[TestMethod]
public void StartStopAndDisposeSchedulerService()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(FakeSchedulerService));
}).Build();
var service = (FakeSchedulerService)host.Services.GetService(typeof(IHostedService));
Assert.NotNull(service);
host.Start();
Assert.True(service.IsStarted);
Thread.Sleep(20);
Assert.True(service.IsCompleted);
host.Stop();
Assert.True(service.IsStopped);
host.Dispose();
}
[TestMethod]
public void StartStopSchedulerServiceThrowsAggregateException()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddHostedService(typeof(ExecptionSchedulerService));
}).Build();
Assert.Throws(typeof(AggregateException),
() => host.Start());
Assert.Throws(typeof(AggregateException),
() => host.Stop());
}
}
public class FakeSchedulerService : SchedulerService
{
public bool IsStarted { get; set; } = false;
public bool IsCompleted { get; set; } = false;
public bool IsStopped { get; set; } = false;
public FakeSchedulerService()
: base(TimeSpan.FromMilliseconds(10))
{
}
public override void Start()
{
IsStarted = true;
base.Start();
}
protected override void ExecuteAsync(object state)
{
IsCompleted = true;
}
public override void Stop()
{
IsStopped = true;
base.Stop();
}
}
public class ExecptionSchedulerService : SchedulerService
{
public ExecptionSchedulerService()
: base(TimeSpan.FromSeconds(1))
{
}
public override void Start()
{
base.Start();
throw new NotImplementedException();
}
protected override void ExecuteAsync(object state)
{
throw new NotImplementedException();
}
public override void Stop()
{
base.Stop();
throw new NotImplementedException();
}
}
}

14
tests/nano.runsettings Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
<MaxCpuCount>1</MaxCpuCount>
<ResultsDirectory>.\TestResults</ResultsDirectory><!-- Path relative to solution directory -->
<TestSessionTimeout>120000</TestSessionTimeout><!-- Milliseconds -->
<TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
</RunConfiguration>
<nanoFrameworkAdapter>
<Logging>None</Logging>
<IsRealHardware>False</IsRealHardware>
</nanoFrameworkAdapter>
</RunSettings>

Просмотреть файл

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<ItemGroup>
<ProjectCapability Include="TestContainer" />
</ItemGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>450af2b8-2c40-4c3d-bee3-091f01bd97f1</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>nanoFramework.Hosting.UnitTests</RootNamespace>
<AssemblyName>NFUnitTest</AssemblyName>
<IsCodedUITest>False</IsCodedUITest>
<IsTestProject>true</IsTestProject>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<PropertyGroup>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\nano.runsettings</RunSettingsFilePath>
</PropertyGroup>
<ItemGroup>
<Compile Include="BackgroundServiceTests.cs" />
<Compile Include="HostingTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="HostedServiceTests.cs" />
<Compile Include="SchedulerServiceTests.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.DependencyInjection">
<HintPath>..\packages\nanoFramework.DependencyInjection.1.0.0.11\lib\nanoFramework.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.TestFramework">
<HintPath>..\packages\nanoFramework.TestFramework.1.0.209\lib\nanoFramework.TestFramework.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.UnitTestLauncher">
<HintPath>..\packages\nanoFramework.TestFramework.1.0.209\lib\nanoFramework.UnitTestLauncher.exe</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="nano.runsettings" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\nanoFramework.Hosting\nanoFramework.Hosting.nfproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Fakes\" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<!-- MANUAL UPDATE HERE -->
<Import Project="..\packages\nanoFramework.TestFramework.1.0.205\build\nanoFramework.TestFramework.targets" Condition="Exists('..\packages\nanoFramework.TestFramework.1.0.205\build\nanoFramework.TestFramework.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<WarningText>Update the Import path in nfproj to the correct nanoFramework.TestFramework NuGet package folder.</WarningText>
</PropertyGroup>
<Warning Condition="!Exists('..\packages\nanoFramework.TestFramework.1.0.205\build\nanoFramework.TestFramework.targets')" Text="'$(WarningText)'" />
</Target>
</Project>

6
tests/packages.config Normal file
Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.12.0" targetFramework="netnano1.0" />
<package id="nanoFramework.DependencyInjection" version="1.0.0.11" targetFramework="netnano1.0" />
<package id="nanoFramework.TestFramework" version="1.0.209" targetFramework="netnano1.0" developmentDependency="true" />
</packages>