diff --git a/README.md b/README.md
index 18d74de8..76331634 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ The **Solid Instruments** constituent libraries expose a wide variety of powerfu
[![Service](doc/images/Label.Service.300w.png)](src/RapidField.SolidInstruments.Service/README.md)
[![Signal Processing](doc/images/Label.SignalProcessing.300w.png)](src/RapidField.SolidInstruments.SignalProcessing/README.md)
[![Text Encoding](doc/images/Label.TextEncoding.300w.png)](src/RapidField.SolidInstruments.TextEncoding/README.md)
+[![Web](doc/images/Label.Web.300w.png)](src/RapidField.SolidInstruments.Web/README.md)
## License
diff --git a/RapidField.SolidInstruments.sln b/RapidField.SolidInstruments.sln
index 6b06ab85..e267d24a 100644
--- a/RapidField.SolidInstruments.sln
+++ b/RapidField.SolidInstruments.sln
@@ -165,6 +165,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{3A9700
doc\images\Icon.Service.128w.png = doc\images\Icon.Service.128w.png
doc\images\Icon.SignalProcessing.128w.png = doc\images\Icon.SignalProcessing.128w.png
doc\images\Icon.TextEncoding.128w.png = doc\images\Icon.TextEncoding.128w.png
+ doc\images\Icon.Web.128w.png = doc\images\Icon.Web.128w.png
doc\images\Label.Collections.300w.png = doc\images\Label.Collections.300w.png
doc\images\Label.Command.300w.png = doc\images\Label.Command.300w.png
doc\images\Label.Core.300w.png = doc\images\Label.Core.300w.png
@@ -179,6 +180,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{3A9700
doc\images\Label.Service.300w.png = doc\images\Label.Service.300w.png
doc\images\Label.SignalProcessing.300w.png = doc\images\Label.SignalProcessing.300w.png
doc\images\Label.TextEncoding.300w.png = doc\images\Label.TextEncoding.300w.png
+ doc\images\Label.Web.300w.png = doc\images\Label.Web.300w.png
doc\images\RapidField.Logo.Color.White.Transparent.227w.png = doc\images\RapidField.Logo.Color.White.Transparent.227w.png
doc\images\SolidInstruments.Logo.Color.Black.Transparent.500w.png = doc\images\SolidInstruments.Logo.Color.Black.Transparent.500w.png
EndProjectSection
@@ -260,6 +262,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "namespaces", "namespaces",
doc\namespaces\RapidField.SolidInstruments.SignalProcessing.md = doc\namespaces\RapidField.SolidInstruments.SignalProcessing.md
doc\namespaces\RapidField.SolidInstruments.TextEncoding.Extensions.md = doc\namespaces\RapidField.SolidInstruments.TextEncoding.Extensions.md
doc\namespaces\RapidField.SolidInstruments.TextEncoding.md = doc\namespaces\RapidField.SolidInstruments.TextEncoding.md
+ doc\namespaces\RapidField.SolidInstruments.Web.Autofac.Extensions.md = doc\namespaces\RapidField.SolidInstruments.Web.Autofac.Extensions.md
+ doc\namespaces\RapidField.SolidInstruments.Web.Autofac.md = doc\namespaces\RapidField.SolidInstruments.Web.Autofac.md
+ doc\namespaces\RapidField.SolidInstruments.Web.DotNetNative.Extensions.md = doc\namespaces\RapidField.SolidInstruments.Web.DotNetNative.Extensions.md
+ doc\namespaces\RapidField.SolidInstruments.Web.DotNetNative.md = doc\namespaces\RapidField.SolidInstruments.Web.DotNetNative.md
+ doc\namespaces\RapidField.SolidInstruments.Web.md = doc\namespaces\RapidField.SolidInstruments.Web.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{5D1D074E-456F-4CA1-A4C5-45074EDCFDA8}"
@@ -407,9 +414,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi", "example\RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi\RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.csproj", "{AC2D0816-3ABF-4458-80DB-E4BADDD9A2E0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RapidField.SolidInstruments.Example.Domain.Identity", "example\RapidField.SolidInstruments.Example.Domain.Identity\RapidField.SolidInstruments.Example.Domain.Identity.csproj", "{630F6AC9-3A4C-4B8A-B55D-D44A7BFBB025}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments.Example.Domain.Identity", "example\RapidField.SolidInstruments.Example.Domain.Identity\RapidField.SolidInstruments.Example.Domain.Identity.csproj", "{630F6AC9-3A4C-4B8A-B55D-D44A7BFBB025}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RapidField.SolidInstruments.Example.Domain.Identity.Service", "example\RapidField.SolidInstruments.Example.Domain.Identity.Service\RapidField.SolidInstruments.Example.Domain.Identity.Service.csproj", "{352E9021-1010-4A5D-8435-F8331DA63F95}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidField.SolidInstruments.Example.Domain.Identity.Service", "example\RapidField.SolidInstruments.Example.Domain.Identity.Service\RapidField.SolidInstruments.Example.Domain.Identity.Service.csproj", "{352E9021-1010-4A5D-8435-F8331DA63F95}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RapidField.SolidInstruments.Web", "src\RapidField.SolidInstruments.Web\RapidField.SolidInstruments.Web.csproj", "{3F1A6F2B-B84F-44C5-9E7D-5763C82CA926}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RapidField.SolidInstruments.Web.Autofac", "src\RapidField.SolidInstruments.Web.Autofac\RapidField.SolidInstruments.Web.Autofac.csproj", "{20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RapidField.SolidInstruments.Web.DotNetNative", "src\RapidField.SolidInstruments.Web.DotNetNative\RapidField.SolidInstruments.Web.DotNetNative.csproj", "{6A53C072-71C8-42F1-90D9-9AE64F2848B2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -649,6 +662,18 @@ Global
{352E9021-1010-4A5D-8435-F8331DA63F95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{352E9021-1010-4A5D-8435-F8331DA63F95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{352E9021-1010-4A5D-8435-F8331DA63F95}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926}.Release|Any CPU.Build.0 = Release|Any CPU
+ {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6A53C072-71C8-42F1-90D9-9AE64F2848B2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -728,6 +753,9 @@ Global
{AC2D0816-3ABF-4458-80DB-E4BADDD9A2E0} = {BEB60D41-11BB-4C6E-8F5D-1E7990A27C34}
{630F6AC9-3A4C-4B8A-B55D-D44A7BFBB025} = {BEB60D41-11BB-4C6E-8F5D-1E7990A27C34}
{352E9021-1010-4A5D-8435-F8331DA63F95} = {BEB60D41-11BB-4C6E-8F5D-1E7990A27C34}
+ {3F1A6F2B-B84F-44C5-9E7D-5763C82CA926} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7}
+ {20452BD4-3C2F-44EC-8DEB-14FD9FE8AA84} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7}
+ {6A53C072-71C8-42F1-90D9-9AE64F2848B2} = {F58E05BE-9DC6-41B4-8324-C006F6CE7CC7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {834FCFB0-DA00-4ABD-9424-6FE1398A9F6E}
diff --git a/doc/images/Icon.Web.128w.png b/doc/images/Icon.Web.128w.png
new file mode 100644
index 00000000..200a4778
Binary files /dev/null and b/doc/images/Icon.Web.128w.png differ
diff --git a/doc/images/Label.Web.300w.png b/doc/images/Label.Web.300w.png
new file mode 100644
index 00000000..5d6835ff
Binary files /dev/null and b/doc/images/Label.Web.300w.png differ
diff --git a/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.Extensions.md b/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.Extensions.md
new file mode 100644
index 00000000..fbd7eb31
--- /dev/null
+++ b/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.Extensions.md
@@ -0,0 +1,31 @@
+---
+uid: RapidField.SolidInstruments.Web.Autofac.Extensions
+summary: *content
+---
+
+
+
+Exposes extensions that support the [**Autofac**](https://autofac.org/) integration for the **Solid Instruments** web application abstractions.
+
+
+
+![Web label](../images/Label.Web.300w.png)
+- - -
+
+### Installation
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.Autofac
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.Autofac
+```
\ No newline at end of file
diff --git a/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.md b/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.md
new file mode 100644
index 00000000..e31ecabb
--- /dev/null
+++ b/doc/namespaces/RapidField.SolidInstruments.Web.Autofac.md
@@ -0,0 +1,39 @@
+---
+uid: RapidField.SolidInstruments.Web.Autofac
+summary: *content
+---
+
+
+
+Exposes the [**Autofac**](https://autofac.org/) integration for the **Solid Instruments** web application abstractions.
+
+
+
+![Web label](../images/Label.Web.300w.png)
+- - -
+
+### Installation
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.Autofac
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.Autofac
+```
+
+### Namespaces
+
+#### [RapidField.SolidInstruments.Web.Autofac.Extensions](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.Autofac.Extensions.html)
+
+
+Exposes extensions that support the Autofac integration for the Solid Instruments web application abstractions.
+
\ No newline at end of file
diff --git a/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.Extensions.md b/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.Extensions.md
new file mode 100644
index 00000000..ada4bad5
--- /dev/null
+++ b/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.Extensions.md
@@ -0,0 +1,31 @@
+---
+uid: RapidField.SolidInstruments.Web.DotNetNative.Extensions
+summary: *content
+---
+
+
+
+Exposes extensions that support the native .NET IoC integration for the **Solid Instruments** web application abstractions.
+
+
+
+![Web label](../images/Label.Web.300w.png)
+- - -
+
+### Installation
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.DotNetNative
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.DotNetNative
+```
\ No newline at end of file
diff --git a/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.md b/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.md
new file mode 100644
index 00000000..94886f85
--- /dev/null
+++ b/doc/namespaces/RapidField.SolidInstruments.Web.DotNetNative.md
@@ -0,0 +1,39 @@
+---
+uid: RapidField.SolidInstruments.Web.DotNetNative
+summary: *content
+---
+
+
+
+Exposes the native .NET IoC integration for the **Solid Instruments** web application abstractions.
+
+
+
+![Web label](../images/Label.Web.300w.png)
+- - -
+
+### Installation
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.DotNetNative
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.DotNetNative
+```
+
+### Namespaces
+
+#### [RapidField.SolidInstruments.Web.DotNetNative.Extensions](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.DotNetNative.Extensions.html)
+
+
+Exposes extensions that support the native .NET IoC integration for the Solid Instruments web application abstractions.
+
\ No newline at end of file
diff --git a/doc/namespaces/RapidField.SolidInstruments.Web.md b/doc/namespaces/RapidField.SolidInstruments.Web.md
new file mode 100644
index 00000000..22f5ef6b
--- /dev/null
+++ b/doc/namespaces/RapidField.SolidInstruments.Web.md
@@ -0,0 +1,31 @@
+---
+uid: RapidField.SolidInstruments.Web
+summary: *content
+---
+
+
+
+Exposes types that simplify web application design.
+
+
+
+![Web label](../images/Label.Web.300w.png)
+- - -
+
+### Installation
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web
+```
\ No newline at end of file
diff --git a/en-US_User.dic b/en-US_User.dic
index 3b802546..87c905a9 100644
--- a/en-US_User.dic
+++ b/en-US_User.dic
@@ -113,6 +113,7 @@ foundational
getters
Gitter
Glyphicons
+guid
Halflings
hh
hotfix
diff --git a/example/RapidField.SolidInstruments.Example.BeaconService/ApplicationServiceExecutor.cs b/example/RapidField.SolidInstruments.Example.BeaconService/ApplicationServiceExecutor.cs
index 6f6628de..739ac61d 100644
--- a/example/RapidField.SolidInstruments.Example.BeaconService/ApplicationServiceExecutor.cs
+++ b/example/RapidField.SolidInstruments.Example.BeaconService/ApplicationServiceExecutor.cs
@@ -2,10 +2,8 @@
// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
// =================================================================================================================================
-using Microsoft.Extensions.Configuration;
using RapidField.SolidInstruments.Messaging.DotNetNative.Service;
using System;
-using System.IO;
namespace RapidField.SolidInstruments.Example.BeaconService
{
@@ -23,24 +21,6 @@ public ApplicationServiceExecutor()
return;
}
- ///
- /// Builds the application configuration for the service.
- ///
- ///
- /// An object that is used to build the configuration.
- ///
- protected override void BuildConfiguration(IConfigurationBuilder configurationBuilder)
- {
- try
- {
- configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
- }
- finally
- {
- base.BuildConfiguration(configurationBuilder);
- }
- }
-
///
/// Releases all resources consumed by the current .
///
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyModule.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyModule.cs
new file mode 100644
index 00000000..f8c70c60
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyModule.cs
@@ -0,0 +1,43 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using RapidField.SolidInstruments.InversionOfControl.DotNetNative;
+using System;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi
+{
+ ///
+ /// Encapsulates container configuration for application dependencies.
+ ///
+ public sealed class ApplicationDependencyModule : DotNetNativeDependencyModule
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// is .
+ ///
+ public ApplicationDependencyModule(IConfiguration applicationConfiguration)
+ : base(applicationConfiguration)
+ {
+ return;
+ }
+
+ ///
+ /// Configures the module.
+ ///
+ ///
+ /// An object that configures containers.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ protected override void Configure(ServiceCollection configurator, IConfiguration applicationConfiguration) => _ = configurator.AddControllers();
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs
index fc762217..1a8202e0 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationDependencyPackage.cs
@@ -35,6 +35,7 @@ public ApplicationDependencyPackage()
///
protected override IEnumerable> CreateModules(IConfiguration applicationConfiguration) => new IDependencyModule[]
{
+ new ApplicationDependencyModule(applicationConfiguration),
new DatabaseContextDependencyModule(applicationConfiguration),
new ServiceBusDependencyModule(applicationConfiguration),
new MessageHandlerModule(applicationConfiguration)
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationWebExecutor.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationWebExecutor.cs
new file mode 100644
index 00000000..b5ea7ff2
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/ApplicationWebExecutor.cs
@@ -0,0 +1,84 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Configuration;
+using RapidField.SolidInstruments.Web.DotNetNative;
+using System;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi
+{
+ ///
+ /// Prepares for and performs execution of the HTTP API application.
+ ///
+ public sealed class ApplicationWebExecutor : DotNetNativeWebExecutor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The name of the web application.
+ ///
+ ///
+ /// is empty.
+ ///
+ ///
+ /// is .
+ ///
+ public ApplicationWebExecutor(String applicationName)
+ : base(applicationName)
+ {
+ return;
+ }
+
+ ///
+ /// Configures the application's request pipeline.
+ ///
+ ///
+ /// An object that configures the application's request pipeline.
+ ///
+ ///
+ /// Configuration information for the web application.
+ ///
+ ///
+ /// Command line arguments that are provided at runtime, if any.
+ ///
+ protected override void ConfigureApplication(IApplicationBuilder application, IConfiguration applicationConfiguration, String[] commandLineArguments)
+ {
+ try
+ {
+ application.UseAuthorization();
+ application.UseRouting();
+ application.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ });
+ }
+ finally
+ {
+ base.ConfigureApplication(application, applicationConfiguration, commandLineArguments);
+ }
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+
+ ///
+ /// When overridden by a derived class, gets a copyright notice which is written to the console at the start of application
+ /// execution.
+ ///
+ protected override sealed String CopyrightNotice => "Copyright (c) RapidField LLC. All rights reserved.";
+
+ ///
+ /// When overridden by a derived class, gets a product name associated with the application which is written to the console
+ /// at the start of application execution.
+ ///
+ protected override sealed String ProductName => "Solid Instruments";
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/TestController.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/TestController.cs
new file mode 100644
index 00000000..2af80642
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/TestController.cs
@@ -0,0 +1,34 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.AspNetCore.Mvc;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.Controllers
+{
+ ///
+ /// Processes HTTP requests for the ~/Test endpoint.
+ ///
+ [Route("[controller]")]
+ [ApiController]
+ public sealed class TestController : ControllerBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TestController()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Handles GET requests for the endpoint.
+ ///
+ ///
+ /// A status code result.
+ ///
+ [HttpGet]
+ public IActionResult Get() => Ok();
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs
index eed70a41..ed09cf8b 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Controllers/UserController.cs
@@ -31,6 +31,7 @@ public sealed class UserController : ControllerBase
/// is .
///
public UserController(ICommandMediator mediator)
+ : base()
{
Mediator = mediator.RejectIf().IsNull(nameof(mediator)).TargetArgument;
}
@@ -45,10 +46,18 @@ public UserController(ICommandMediator mediator)
/// A status code result.
///
[HttpDelete]
- public IActionResult Delete([FromQuery] Guid identifier)
+ public IActionResult Delete([FromRoute] Guid identifier)
{
try
{
+ var model = Mediator.Process(new FindDomainModelByIdentifierCommand(identifier));
+
+ if (model is null)
+ {
+ return NotFound(identifier);
+ }
+
+ _ = Mediator.Process(new DeleteDomainModelCommandMessage(new DeleteDomainModelCommand(model)));
return Ok();
}
catch (ArgumentException exception)
@@ -76,7 +85,13 @@ public IActionResult Get([FromQuery] Guid identifier)
{
try
{
- var model = (DomainModel)null;
+ var model = Mediator.Process(new FindDomainModelByIdentifierCommand(identifier));
+
+ if (model is null)
+ {
+ return NotFound(identifier);
+ }
+
return new JsonResult(model);
}
catch (ArgumentException exception)
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs
index 8ac60e1a..a9a6a45b 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Program.cs
@@ -2,9 +2,8 @@
// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
// =================================================================================================================================
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Hosting;
using System;
+using System.Diagnostics;
namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi
{
@@ -14,25 +13,21 @@ namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi
public static class Program
{
///
- /// Configures the application hosting environment.
+ /// Begins execution of the application.
///
///
/// Command line arguments that are provided at runtime.
///
- ///
- /// The resulting host configuration.
- ///
- public static IHostBuilder CreateHostBuilder(String[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
+ public static void Main(String[] args)
{
- webBuilder.UseStartup();
- });
+ using var webExecutor = new ApplicationWebExecutor(ApplicationName);
+ webExecutor.Execute(args);
+ }
///
- /// Begins execution of the application.
+ /// Represents the name of this application.
///
- ///
- /// Command line arguments that are provided at runtime.
- ///
- public static void Main(String[] args) => CreateHostBuilder(args).Build().Run();
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly String ApplicationName = $"{nameof(AccessControl)} HTTP API";
}
}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Properties/launchSettings.json b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Properties/launchSettings.json
index 9a6041f5..a9af1982 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Properties/launchSettings.json
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Properties/launchSettings.json
@@ -4,7 +4,7 @@
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57484",
- "sslPort": 44319
+ "sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.csproj b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.csproj
index 3ce434a5..53217fc8 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.csproj
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi.csproj
@@ -20,6 +20,7 @@ Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in
+
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Startup.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Startup.cs
deleted file mode 100644
index 34859fc7..00000000
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi/Startup.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// =================================================================================================================================
-// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
-// =================================================================================================================================
-
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-
-#pragma warning disable CA1822 // Mark members as static
-
-namespace RapidField.SolidInstruments.Example.Domain.AccessControl.HttpApi
-{
- ///
- /// Encapsulates application startup configuration.
- ///
- public class Startup
- {
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- ///
- ///
- ///
- /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- ///
- ///
- ///
- ///
- ///
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- app.UseHttpsRedirection();
- app.UseRouting();
- app.UseAuthorization();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
-
- ///
- ///
- ///
- /// This method gets called by the runtime. Use this method to add services to the container.
- ///
- ///
- ///
- public void ConfigureServices(IServiceCollection services) => _ = services.AddControllers();
-
- ///
- ///
- public IConfiguration Configuration { get; }
- }
-}
-
-#pragma warning restore CA1822 // Mark members as static
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.Service/ApplicationServiceExecutor.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.Service/ApplicationServiceExecutor.cs
index 772b293b..5ec18659 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.AccessControl.Service/ApplicationServiceExecutor.cs
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl.Service/ApplicationServiceExecutor.cs
@@ -11,7 +11,6 @@
using RapidField.SolidInstruments.Service;
using System;
using System.Diagnostics;
-using System.IO;
using System.Threading;
namespace RapidField.SolidInstruments.Example.Domain.AccessControl.Service
@@ -65,24 +64,6 @@ protected override void AddListeners(IMessageListeningProfile listeningProfile,
}
}
- ///
- /// Builds the application configuration for the service.
- ///
- ///
- /// An object that is used to build the configuration.
- ///
- protected override void BuildConfiguration(IConfigurationBuilder configurationBuilder)
- {
- try
- {
- configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
- }
- finally
- {
- base.BuildConfiguration(configurationBuilder);
- }
- }
-
///
/// Releases all resources consumed by the current .
///
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/User/FindDomainModelByIdentifierCommandHandler.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/User/FindDomainModelByIdentifierCommandHandler.cs
new file mode 100644
index 00000000..a3800db0
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/User/FindDomainModelByIdentifierCommandHandler.cs
@@ -0,0 +1,42 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using RapidField.SolidInstruments.DataAccess;
+using System;
+using DataAccessModel = RapidField.SolidInstruments.Example.Domain.Models.User.AggregateDataAccessModel;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.User.DomainModel;
+using DomainModelCommand = RapidField.SolidInstruments.Example.Domain.Commands.ModelState.User.FindDomainModelByIdentifierCommand;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.CommandHandlers.ModelState.User
+{
+ ///
+ /// Processes a single .
+ ///
+ public sealed class FindDomainModelByIdentifierCommandHandler : FindDomainModelByIdentifierCommandHandler
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRole/FindDomainModelByIdentifierCommandHandler.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRole/FindDomainModelByIdentifierCommandHandler.cs
new file mode 100644
index 00000000..72672d7d
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRole/FindDomainModelByIdentifierCommandHandler.cs
@@ -0,0 +1,42 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using RapidField.SolidInstruments.DataAccess;
+using System;
+using DataAccessModel = RapidField.SolidInstruments.Example.Domain.Models.UserRole.AggregateDataAccessModel;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.UserRole.DomainModel;
+using DomainModelCommand = RapidField.SolidInstruments.Example.Domain.Commands.ModelState.UserRole.FindDomainModelByIdentifierCommand;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.CommandHandlers.ModelState.UserRole
+{
+ ///
+ /// Processes a single .
+ ///
+ public sealed class FindDomainModelByIdentifierCommandHandler : FindDomainModelByIdentifierCommandHandler
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommandHandler.cs b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommandHandler.cs
new file mode 100644
index 00000000..f1673fb6
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain.AccessControl/CommandHandlers/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommandHandler.cs
@@ -0,0 +1,42 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using RapidField.SolidInstruments.DataAccess;
+using System;
+using DataAccessModel = RapidField.SolidInstruments.Example.Domain.Models.UserRoleAssignment.AggregateDataAccessModel;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.UserRoleAssignment.DomainModel;
+using DomainModelCommand = RapidField.SolidInstruments.Example.Domain.Commands.ModelState.UserRoleAssignment.FindDomainModelByIdentifierCommand;
+
+namespace RapidField.SolidInstruments.Example.Domain.AccessControl.CommandHandlers.ModelState.UserRoleAssignment
+{
+ ///
+ /// Processes a single .
+ ///
+ public sealed class FindDomainModelByIdentifierCommandHandler : FindDomainModelByIdentifierCommandHandler
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain.Identity.Service/ApplicationServiceExecutor.cs b/example/RapidField.SolidInstruments.Example.Domain.Identity.Service/ApplicationServiceExecutor.cs
index c5d1f9e3..06f084f8 100644
--- a/example/RapidField.SolidInstruments.Example.Domain.Identity.Service/ApplicationServiceExecutor.cs
+++ b/example/RapidField.SolidInstruments.Example.Domain.Identity.Service/ApplicationServiceExecutor.cs
@@ -11,7 +11,6 @@
using RapidField.SolidInstruments.Service;
using System;
using System.Diagnostics;
-using System.IO;
using System.Threading;
namespace RapidField.SolidInstruments.Example.Domain.Identity.Service
@@ -65,24 +64,6 @@ protected override void AddListeners(IMessageListeningProfile listeningProfile,
}
}
- ///
- /// Builds the application configuration for the service.
- ///
- ///
- /// An object that is used to build the configuration.
- ///
- protected override void BuildConfiguration(IConfigurationBuilder configurationBuilder)
- {
- try
- {
- configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
- }
- finally
- {
- base.BuildConfiguration(configurationBuilder);
- }
- }
-
///
/// Releases all resources consumed by the current .
///
diff --git a/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/User/FindDomainModelByIdentifierCommand.cs b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/User/FindDomainModelByIdentifierCommand.cs
new file mode 100644
index 00000000..b6bdbaf6
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/User/FindDomainModelByIdentifierCommand.cs
@@ -0,0 +1,89 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.Serialization;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.User.DomainModel;
+
+namespace RapidField.SolidInstruments.Example.Domain.Commands.ModelState.User
+{
+ ///
+ /// Represents a command to find and return a by its primary identifier.
+ ///
+ [DataContract(Name = DataContractName)]
+ public sealed class FindDomainModelByIdentifierCommand : FindDomainModelByIdentifierCommand
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FindDomainModelByIdentifierCommand()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier)
+ : base(modelIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels)
+ : base(modelIdentifier, labels)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels, Guid correlationIdentifier)
+ : base(modelIdentifier, labels, correlationIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Represents the name that is used when representing this type in serialization and transport contexts.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal const String DataContractName = DataContractNameVerb + DomainModel.DataContractName + DataContractNamePreposition + DataContractNameSuffix;
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRole/FindDomainModelByIdentifierCommand.cs b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRole/FindDomainModelByIdentifierCommand.cs
new file mode 100644
index 00000000..1d4f0ebf
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRole/FindDomainModelByIdentifierCommand.cs
@@ -0,0 +1,89 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.Serialization;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.UserRole.DomainModel;
+
+namespace RapidField.SolidInstruments.Example.Domain.Commands.ModelState.UserRole
+{
+ ///
+ /// Represents a command to find and return a by its primary identifier.
+ ///
+ [DataContract(Name = DataContractName)]
+ public sealed class FindDomainModelByIdentifierCommand : FindDomainModelByIdentifierCommand
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FindDomainModelByIdentifierCommand()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier)
+ : base(modelIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels)
+ : base(modelIdentifier, labels)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels, Guid correlationIdentifier)
+ : base(modelIdentifier, labels, correlationIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Represents the name that is used when representing this type in serialization and transport contexts.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal const String DataContractName = DataContractNameVerb + DomainModel.DataContractName + DataContractNamePreposition + DataContractNameSuffix;
+ }
+}
\ No newline at end of file
diff --git a/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommand.cs b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommand.cs
new file mode 100644
index 00000000..81f42322
--- /dev/null
+++ b/example/RapidField.SolidInstruments.Example.Domain/Commands/ModelState/UserRoleAssignment/FindDomainModelByIdentifierCommand.cs
@@ -0,0 +1,89 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.Serialization;
+using DomainModel = RapidField.SolidInstruments.Example.Domain.Models.UserRoleAssignment.DomainModel;
+
+namespace RapidField.SolidInstruments.Example.Domain.Commands.ModelState.UserRoleAssignment
+{
+ ///
+ /// Represents a command to find and return a by its primary identifier.
+ ///
+ [DataContract(Name = DataContractName)]
+ public sealed class FindDomainModelByIdentifierCommand : FindDomainModelByIdentifierCommand
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FindDomainModelByIdentifierCommand()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier)
+ : base(modelIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels)
+ : base(modelIdentifier, labels)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelByIdentifierCommand(Guid modelIdentifier, IEnumerable labels, Guid correlationIdentifier)
+ : base(modelIdentifier, labels, correlationIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Represents the name that is used when representing this type in serialization and transport contexts.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal const String DataContractName = DataContractNameVerb + DomainModel.DataContractName + DataContractNamePreposition + DataContractNameSuffix;
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/DomainCommand.cs b/src/RapidField.SolidInstruments.Command/DomainCommand.cs
index f6cf555c..eafb0f0b 100644
--- a/src/RapidField.SolidInstruments.Command/DomainCommand.cs
+++ b/src/RapidField.SolidInstruments.Command/DomainCommand.cs
@@ -46,7 +46,7 @@ public DomainCommand(Guid correlationIdentifier)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// is .
@@ -61,7 +61,7 @@ public DomainCommand(IEnumerable labels)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// A unique identifier that is assigned to related commands.
@@ -130,7 +130,7 @@ public DomainCommand(Guid correlationIdentifier)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// is .
@@ -145,7 +145,7 @@ public DomainCommand(IEnumerable labels)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// A unique identifier that is assigned to related commands.
diff --git a/src/RapidField.SolidInstruments.Command/DomainModelCommand.cs b/src/RapidField.SolidInstruments.Command/DomainModelCommand.cs
index eec75bcd..c2a9559b 100644
--- a/src/RapidField.SolidInstruments.Command/DomainModelCommand.cs
+++ b/src/RapidField.SolidInstruments.Command/DomainModelCommand.cs
@@ -54,7 +54,7 @@ public DomainModelCommand(Guid correlationIdentifier)
/// The desired state of the associated domain model.
///
///
- /// A classification that describes the effect of a the event upon .
+ /// A classification that describes the effect of a the command upon .
///
///
/// is .
@@ -75,7 +75,7 @@ public DomainModelCommand(TModel model, DomainModelCommandClassification classif
/// The desired state of the associated domain model.
///
///
- /// A classification that describes the effect of a the event upon .
+ /// A classification that describes the effect of a the command upon .
///
///
/// A unique identifier that is assigned to related commands.
@@ -100,10 +100,10 @@ public DomainModelCommand(TModel model, DomainModelCommandClassification classif
/// The desired state of the associated domain model.
///
///
- /// A classification that describes the effect of a the event upon .
+ /// A classification that describes the effect of a the command upon .
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// is -or- is .
@@ -125,10 +125,10 @@ public DomainModelCommand(TModel model, DomainModelCommandClassification classif
/// The desired state of the associated domain model.
///
///
- /// A classification that describes the effect of a the event upon .
+ /// A classification that describes the effect of a the command upon .
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// A unique identifier that is assigned to related commands.
diff --git a/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommand.cs b/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommand.cs
new file mode 100644
index 00000000..0ad5161b
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommand.cs
@@ -0,0 +1,109 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Represents a command to find and return an object that models a domain construct by its primary identifier.
+ ///
+ ///
+ /// is the default implementation of
+ /// .
+ ///
+ ///
+ /// The type of the unique primary identifier for the model.
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ [DataContract]
+ public class FindDomainModelByIdentifierCommand : FindDomainModelCommand, IFindDomainModelByIdentifierCommand
+ where TIdentifier : IComparable, IComparable, IEquatable
+ where TModel : class, IDomainModel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FindDomainModelByIdentifierCommand()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ public FindDomainModelByIdentifierCommand(TIdentifier modelIdentifier)
+ : base()
+ {
+ ModelIdentifier = modelIdentifier;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommand(TIdentifier modelIdentifier, IEnumerable labels)
+ : base(labels)
+ {
+ ModelIdentifier = modelIdentifier;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A value that uniquely identifies the associated .
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelByIdentifierCommand(TIdentifier modelIdentifier, IEnumerable labels, Guid correlationIdentifier)
+ : base(labels, correlationIdentifier)
+ {
+ ModelIdentifier = modelIdentifier;
+ }
+
+ ///
+ /// Gets or sets a value that uniquely identifies the associated .
+ ///
+ [DataMember]
+ public TIdentifier ModelIdentifier
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Represents the standard preposition which is included in the name that is used when representing this type in
+ /// serialization and transport contexts.
+ ///
+ protected internal const String DataContractNamePreposition = "ByIdentifier";
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommandHandler.cs b/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommandHandler.cs
new file mode 100644
index 00000000..5c2a15e7
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/FindDomainModelByIdentifierCommandHandler.cs
@@ -0,0 +1,99 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Concurrency;
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+using System.Collections.Generic;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Processes a single .
+ ///
+ ///
+ /// The type of the unique primary identifier for the model.
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ ///
+ /// The type of the command that is processed by the handler.
+ ///
+ public abstract class FindDomainModelByIdentifierCommandHandler : FindDomainModelCommandHandler
+ where TIdentifier : IComparable, IComparable, IEquatable
+ where TModel : class, IDomainModel
+ where TCommand : class, IFindDomainModelByIdentifierCommand
+ {
+ ///
+ /// Initializes a new instance of the
+ /// class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ protected FindDomainModelByIdentifierCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current
+ /// .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+
+ ///
+ /// Searches for and returns the specified domain model.
+ ///
+ ///
+ /// The unique primary identifier for the model.
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier to assign to sub-commands.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// A token that represents and manages contextual thread safety.
+ ///
+ ///
+ /// The specified model, or if no matching model is found.
+ ///
+ protected abstract TModel FindDomainModel(TIdentifier modelIdentifier, IEnumerable labels, Guid correlationIdentifier, ICommandMediator mediator, IConcurrencyControlToken controlToken);
+
+ ///
+ /// Processes the specified command.
+ ///
+ ///
+ /// Do not process using , as doing so will generally result in
+ /// infinite-looping; is exposed to this method to facilitate sub-command processing.
+ ///
+ ///
+ /// The command to process.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands. Do not process using
+ /// , as doing so will generally result in infinite-looping.
+ ///
+ ///
+ /// A token that represents and manages contextual thread safety.
+ ///
+ ///
+ /// The result that is emitted when processing the command.
+ ///
+ protected sealed override TModel Process(TCommand command, ICommandMediator mediator, IConcurrencyControlToken controlToken) => FindDomainModel(command.ModelIdentifier, command.Labels, command.CorrelationIdentifier, mediator, controlToken);
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/FindDomainModelCommand.cs b/src/RapidField.SolidInstruments.Command/FindDomainModelCommand.cs
new file mode 100644
index 00000000..970febb7
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/FindDomainModelCommand.cs
@@ -0,0 +1,92 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Represents a command to find and return an object that models a domain construct.
+ ///
+ ///
+ /// is the default implementation of
+ /// .
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ [DataContract]
+ public class FindDomainModelCommand : DomainCommand, IFindDomainModelCommand
+ where TModel : class, IDomainModel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FindDomainModelCommand()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelCommand(Guid correlationIdentifier)
+ : base(correlationIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelCommand(IEnumerable labels)
+ : base(labels)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier that is assigned to related commands.
+ ///
+ ///
+ /// is .
+ ///
+ ///
+ /// is equal to .
+ ///
+ public FindDomainModelCommand(IEnumerable labels, Guid correlationIdentifier)
+ : base(labels, correlationIdentifier)
+ {
+ return;
+ }
+
+ ///
+ /// Represents the standard verb which is prefixed to the name that is used when representing this type in serialization and
+ /// transport contexts.
+ ///
+ protected internal const String DataContractNameVerb = "Find";
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/FindDomainModelCommandHandler.cs b/src/RapidField.SolidInstruments.Command/FindDomainModelCommandHandler.cs
new file mode 100644
index 00000000..a66f2cb3
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/FindDomainModelCommandHandler.cs
@@ -0,0 +1,46 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Processes a single .
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ ///
+ /// The type of the command that is processed by the handler.
+ ///
+ public abstract class FindDomainModelCommandHandler : DomainCommandHandler
+ where TModel : class, IDomainModel
+ where TCommand : class, IFindDomainModelCommand
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ protected FindDomainModelCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/IFindDomainModelByIdentifierCommand.cs b/src/RapidField.SolidInstruments.Command/IFindDomainModelByIdentifierCommand.cs
new file mode 100644
index 00000000..a2be732f
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/IFindDomainModelByIdentifierCommand.cs
@@ -0,0 +1,32 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Represents a command to find and return an object that models a domain construct by its primary identifier.
+ ///
+ ///
+ /// The type of the unique primary identifier for the model.
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ public interface IFindDomainModelByIdentifierCommand : IFindDomainModelCommand
+ where TIdentifier : IComparable, IComparable, IEquatable
+ where TModel : class, IDomainModel
+ {
+ ///
+ /// Gets or sets a value that uniquely identifies the associated .
+ ///
+ public TIdentifier ModelIdentifier
+ {
+ get;
+ set;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Command/IFindDomainModelCommand.cs b/src/RapidField.SolidInstruments.Command/IFindDomainModelCommand.cs
new file mode 100644
index 00000000..da23eb70
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Command/IFindDomainModelCommand.cs
@@ -0,0 +1,19 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core.Domain;
+
+namespace RapidField.SolidInstruments.Command
+{
+ ///
+ /// Represents a command to find and return an object that models a domain construct.
+ ///
+ ///
+ /// The type of the associated domain model.
+ ///
+ public interface IFindDomainModelCommand : IDomainCommand
+ where TModel : class, IDomainModel
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Core/ReferenceManager.cs b/src/RapidField.SolidInstruments.Core/ReferenceManager.cs
index 56ab6ddc..d4afce35 100644
--- a/src/RapidField.SolidInstruments.Core/ReferenceManager.cs
+++ b/src/RapidField.SolidInstruments.Core/ReferenceManager.cs
@@ -45,11 +45,12 @@ public void AddObject(T reference)
using (var controlToken = StateControl.Enter())
{
RejectIfDisposed();
+ Prune();
var managedReference = new ManagedReference(reference);
if (References.Contains(managedReference) == false)
{
- References.Enqueue(managedReference);
+ References.Add(managedReference);
}
}
}
@@ -74,33 +75,29 @@ protected override void Dispose(Boolean disposing)
{
if (disposing)
{
- try
+ while (References.Any())
{
- var disposeTasks = new List();
-
- while (References.Count > 0)
+ try
{
- IAsyncDisposable reference;
+ var disposeTasks = new List();
- using (var controlToken = StateControl.Enter())
+ foreach (var reference in References.ToArray())
{
- reference = References.Dequeue();
+ disposeTasks.Add(reference?.DisposeAsync().AsTask());
}
- disposeTasks.Add(reference?.DisposeAsync().AsTask());
- }
-
- var disposeTaskArray = disposeTasks.Where(task => (task is null) == false).ToArray();
+ var disposeTaskArray = disposeTasks.Where(task => (task is null) == false).ToArray();
- if (disposeTaskArray.Any())
+ if (disposeTaskArray.Any())
+ {
+ Task.WaitAll(disposeTaskArray);
+ }
+ }
+ finally
{
- Task.WaitAll(disposeTaskArray);
+ References.Clear();
}
}
- finally
- {
- References.Clear();
- }
}
}
finally
@@ -109,6 +106,28 @@ protected override void Dispose(Boolean disposing)
}
}
+ ///
+ /// Removes dead references from the current .
+ ///
+ [DebuggerHidden]
+ private void Prune()
+ {
+ if (References.Any())
+ {
+ foreach (var reference in References)
+ {
+ reference.Poll();
+ }
+
+ var deadReferences = References.Where(reference => reference.IsDead);
+
+ foreach (var deadReference in deadReferences)
+ {
+ References.Remove(deadReference);
+ }
+ }
+ }
+
///
/// Gets the number of objects that are managed by the current .
///
@@ -118,15 +137,18 @@ protected override void Dispose(Boolean disposing)
/// Represents the objects that are managed by the current .
///
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
- private readonly Queue References = new Queue();
+ private readonly IList References = new List();
///
/// Represents an object that is managed by a .
///
+ ///
+ /// is the default implementation of .
+ ///
///
/// The type of the managed object.
///
- private class ManagedReference : IAsyncDisposable, IDisposable, IEquatable>
+ private class ManagedReference : IEquatable>, IManagedReference
where T : class
{
///
@@ -138,6 +160,7 @@ private class ManagedReference : IAsyncDisposable, IDisposable, IEquatable other)
///
/// A 32-bit signed integer hash code.
///
- public override Int32 GetHashCode() => Target.GetHashCode();
+ public override Int32 GetHashCode() => Target?.GetHashCode() ?? 0;
+
+ ///
+ /// Destroys the strong reference to the managed object if its lifespan is expired.
+ ///
+ public void Poll()
+ {
+ if (StrongReferenceIsExpired)
+ {
+ StrongReference = null;
+ }
+ }
///
/// Releases all resources consumed by the current .
@@ -290,10 +324,93 @@ protected void Dispose(Boolean disposing)
}
///
- /// Represents the managed object.
+ /// Gets a value indicating whether or not the managed object has live references.
+ ///
+ public Boolean IsDead => Target is null;
+
+ ///
+ /// Gets the length of time that the current has existed.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private TimeSpan Age => TimeStamp.Current - CreationTimeStamp;
+
+ ///
+ /// Gets a value indicating whether or not the strong reference is expired.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Boolean StrongReferenceIsExpired => StrongReference is null || Age > StrongReferenceMinimumLifeSpan;
+
+ ///
+ /// Gets or sets the managed object.
///
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
- private T Target;
+ private T Target
+ {
+ [DebuggerHidden]
+ get
+ {
+ if ((StrongReference is null) == false)
+ {
+ return StrongReference;
+ }
+ else if ((WeakReference is null) == false && WeakReference.TryGetTarget(out var target))
+ {
+ return target;
+ }
+
+ return null;
+ }
+ [DebuggerHidden]
+ set
+ {
+ StrongReference = value;
+ WeakReference = value is null ? null : new WeakReference(value);
+ }
+ }
+
+ ///
+ /// Represents the minimum length of time to preserve a strong reference to the managed object. The observed length of
+ /// time may be shorter if the reference manager is disposed.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly TimeSpan StrongReferenceMinimumLifeSpan = TimeSpan.FromSeconds(233);
+
+ ///
+ /// Represents the date and time when the current was created.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly DateTime CreationTimeStamp;
+
+ ///
+ /// Represents a strong reference to the managed object.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private T StrongReference;
+
+ ///
+ /// Represents a weak reference to the managed object.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private WeakReference WeakReference;
+ }
+
+ ///
+ /// Represents an object that is managed by a .
+ ///
+ private interface IManagedReference : IAsyncDisposable, IDisposable
+ {
+ ///
+ /// Destroys the strong reference to the managed object if its lifespan is expired.
+ ///
+ public void Poll();
+
+ ///
+ /// Gets a value indicating whether or not the managed object has live references.
+ ///
+ public Boolean IsDead
+ {
+ get;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.DataAccess/FindDomainModelByIdentifierCommandHandler.cs b/src/RapidField.SolidInstruments.DataAccess/FindDomainModelByIdentifierCommandHandler.cs
new file mode 100644
index 00000000..ae88051d
--- /dev/null
+++ b/src/RapidField.SolidInstruments.DataAccess/FindDomainModelByIdentifierCommandHandler.cs
@@ -0,0 +1,87 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Command;
+using RapidField.SolidInstruments.Core.Concurrency;
+using RapidField.SolidInstruments.Core.Domain;
+using System;
+using System.Collections.Generic;
+
+namespace RapidField.SolidInstruments.DataAccess
+{
+ ///
+ /// Processes a single .
+ ///
+ ///
+ /// The type of the unique primary identifier for the model.
+ ///
+ ///
+ /// The type of the domain model to which the data access model is mapped.
+ ///
+ ///
+ /// The type of the data access model.
+ ///
+ ///
+ /// The type of the command that is processed by the handler.
+ ///
+ public class FindDomainModelByIdentifierCommandHandler : FindDomainModelByIdentifierCommandHandler
+ where TIdentifier : IComparable, IComparable, IEquatable
+ where TDomainModel : class, IDomainModel, new()
+ where TDataAccessModel : class, IDataAccessModel, new()
+ where TCommand : class, IFindDomainModelByIdentifierCommand
+ {
+ ///
+ /// Initializes a new instance of the
+ /// class.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// is .
+ ///
+ public FindDomainModelByIdentifierCommandHandler(ICommandMediator mediator)
+ : base(mediator)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current
+ /// .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+
+ ///
+ /// Searches for and returns the specified domain model.
+ ///
+ ///
+ /// The unique primary identifier for the model.
+ ///
+ ///
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
+ ///
+ ///
+ /// A unique identifier to assign to sub-commands.
+ ///
+ ///
+ /// A processing intermediary that is used to process sub-commands.
+ ///
+ ///
+ /// A token that represents and manages contextual thread safety.
+ ///
+ ///
+ /// The specified model, or if no matching model is found.
+ ///
+ protected override TDomainModel FindDomainModel(TIdentifier modelIdentifier, IEnumerable labels, Guid correlationIdentifier, ICommandMediator mediator, IConcurrencyControlToken controlToken)
+ {
+ var dataAccessModelCommand = new FindDataAccessModelByIdentifierCommand(modelIdentifier);
+ var dataAccessModel = mediator.Process(dataAccessModelCommand);
+ return dataAccessModel?.ToDomainModel();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.EventAuthoring/DomainReportableCommand.cs b/src/RapidField.SolidInstruments.EventAuthoring/DomainReportableCommand.cs
index 3096c228..d90b61f4 100644
--- a/src/RapidField.SolidInstruments.EventAuthoring/DomainReportableCommand.cs
+++ b/src/RapidField.SolidInstruments.EventAuthoring/DomainReportableCommand.cs
@@ -52,7 +52,7 @@ public DomainReportableCommand(Guid correlationIdentifier)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// is .
@@ -67,7 +67,7 @@ public DomainReportableCommand(IEnumerable labels)
/// Initializes a new instance of the class.
///
///
- /// A collection of textual labels that provide categorical and/or contextual information about the event.
+ /// A collection of textual labels that provide categorical and/or contextual information about the command.
///
///
/// A unique identifier that is assigned to related commands.
diff --git a/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceInjector.cs b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceInjector.cs
index f4ac67f5..4032edda 100644
--- a/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceInjector.cs
+++ b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceInjector.cs
@@ -40,7 +40,7 @@ internal AutofacServiceInjector(IServiceCollection serviceDescriptors)
/// The object that configures a container.
///
///
- /// a collection of service descriptors that are added to the configurator.
+ /// A collection of service descriptors that are added to the configurator.
///
protected sealed override void Inject(ContainerBuilder configurator, IServiceCollection serviceDescriptors)
{
diff --git a/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceProviderFactory.cs b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceProviderFactory.cs
new file mode 100644
index 00000000..a25becdc
--- /dev/null
+++ b/src/RapidField.SolidInstruments.InversionOfControl.Autofac/AutofacServiceProviderFactory.cs
@@ -0,0 +1,72 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Autofac;
+using Autofac.Extensions.DependencyInjection;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using RapidField.SolidInstruments.InversionOfControl.Autofac.Extensions;
+using System;
+
+namespace RapidField.SolidInstruments.InversionOfControl.Autofac
+{
+ ///
+ /// Provides an extension point for creating an Autofac container builder and an .
+ ///
+ ///
+ /// The package that configures the engine.
+ ///
+ public class AutofacServiceProviderFactory : ServiceProviderFactory
+ where TPackage : AutofacDependencyPackage, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// is .
+ ///
+ public AutofacServiceProviderFactory(IConfiguration applicationConfiguration)
+ : base(applicationConfiguration)
+ {
+ return;
+ }
+
+ ///
+ /// Creates an .
+ ///
+ ///
+ /// A source configurator.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// An .
+ ///
+ protected override IServiceProvider CreateServiceProvider(ContainerBuilder configurator, IConfiguration applicationConfiguration)
+ {
+ var container = configurator.Build();
+ return new AutofacServiceProvider(container);
+ }
+
+ ///
+ /// Prepares a newly-created instance.
+ ///
+ ///
+ /// The configurator to prepare.
+ ///
+ ///
+ /// A collection of services.
+ ///
+ protected override void PrepareConfigurator(ContainerBuilder configurator, IServiceCollection services)
+ {
+ services.AddDependencyPackage(ApplicationConfiguration);
+ var serviceInjector = new AutofacServiceInjector(services);
+ serviceInjector.Inject(configurator);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceInjector.cs b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceInjector.cs
index 679a10f6..761c3cc2 100644
--- a/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceInjector.cs
+++ b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceInjector.cs
@@ -37,8 +37,14 @@ internal DotNetNativeServiceInjector(IServiceCollection serviceDescriptors)
/// The object that configures a container.
///
///
- /// a collection of service descriptors that are added to the configurator.
+ /// A collection of service descriptors that are added to the configurator.
///
- protected sealed override void Inject(ServiceCollection configurator, IServiceCollection serviceDescriptors) => configurator.Add(serviceDescriptors);
+ protected sealed override void Inject(ServiceCollection configurator, IServiceCollection serviceDescriptors)
+ {
+ foreach (var serviceDescriptor in serviceDescriptors)
+ {
+ configurator.TryAdd(serviceDescriptor);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceProviderFactory.cs b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceProviderFactory.cs
new file mode 100644
index 00000000..585f9433
--- /dev/null
+++ b/src/RapidField.SolidInstruments.InversionOfControl.DotNetNative/DotNetNativeServiceProviderFactory.cs
@@ -0,0 +1,69 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using RapidField.SolidInstruments.InversionOfControl.DotNetNative.Extensions;
+using System;
+
+namespace RapidField.SolidInstruments.InversionOfControl.DotNetNative
+{
+ ///
+ /// Provides an extension point for creating a native .NET container builder and an .
+ ///
+ ///
+ /// The package that configures the engine.
+ ///
+ public class DotNetNativeServiceProviderFactory : ServiceProviderFactory
+ where TPackage : DotNetNativeDependencyPackage, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// is .
+ ///
+ public DotNetNativeServiceProviderFactory(IConfiguration applicationConfiguration)
+ : base(applicationConfiguration)
+ {
+ return;
+ }
+
+ ///
+ /// Creates an .
+ ///
+ ///
+ /// A source configurator.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// An .
+ ///
+ protected override IServiceProvider CreateServiceProvider(ServiceCollection configurator, IConfiguration applicationConfiguration)
+ {
+ _ = configurator.AddDependencyPackage(applicationConfiguration, out var serviceProvider);
+ return serviceProvider;
+ }
+
+ ///
+ /// Prepares a newly-created instance.
+ ///
+ ///
+ /// The configurator to prepare.
+ ///
+ ///
+ /// A collection of services.
+ ///
+ protected override void PrepareConfigurator(ServiceCollection configurator, IServiceCollection services)
+ {
+ var serviceInjector = new DotNetNativeServiceInjector(services);
+ serviceInjector.Inject(configurator);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.InversionOfControl/Extensions/IServiceCollectionExtensions.cs b/src/RapidField.SolidInstruments.InversionOfControl/Extensions/IServiceCollectionExtensions.cs
index d3d12480..bf3176c1 100644
--- a/src/RapidField.SolidInstruments.InversionOfControl/Extensions/IServiceCollectionExtensions.cs
+++ b/src/RapidField.SolidInstruments.InversionOfControl/Extensions/IServiceCollectionExtensions.cs
@@ -96,7 +96,6 @@ internal static IServiceCollection AddDependencyPackage(applicationConfiguration, target);
ReferenceManager.AddObject(engine);
serviceProvider = engine.Provider;
diff --git a/src/RapidField.SolidInstruments.InversionOfControl/ServiceProviderFactory.cs b/src/RapidField.SolidInstruments.InversionOfControl/ServiceProviderFactory.cs
index 13a18b96..5153c1d1 100644
--- a/src/RapidField.SolidInstruments.InversionOfControl/ServiceProviderFactory.cs
+++ b/src/RapidField.SolidInstruments.InversionOfControl/ServiceProviderFactory.cs
@@ -2,6 +2,7 @@
// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
// =================================================================================================================================
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using RapidField.SolidInstruments.Core;
using RapidField.SolidInstruments.Core.ArgumentValidation;
@@ -10,6 +11,93 @@
namespace RapidField.SolidInstruments.InversionOfControl
{
+ ///
+ /// Provides an extension point for creating a container specific builder and an .
+ ///
+ ///
+ /// The type of the object that configures containers.
+ ///
+ public abstract class ServiceProviderFactory : IServiceProviderFactory
+ where TConfigurator : class, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// is .
+ ///
+ protected ServiceProviderFactory(IConfiguration applicationConfiguration)
+ {
+ ApplicationConfiguration = applicationConfiguration.RejectIf().IsNull(nameof(applicationConfiguration)).TargetArgument;
+ }
+
+ ///
+ /// Returns a new instance.
+ ///
+ ///
+ /// The collection of services.
+ ///
+ ///
+ /// A new instance.
+ ///
+ ///
+ /// is .
+ ///
+ public TConfigurator CreateBuilder(IServiceCollection services)
+ {
+ var configurator = new TConfigurator();
+ PrepareConfigurator(configurator, services.RejectIf().IsNull(nameof(services)).TargetArgument);
+ return configurator;
+ }
+
+ ///
+ /// Creates an .
+ ///
+ ///
+ /// A source configurator.
+ ///
+ ///
+ /// An .
+ ///
+ ///
+ /// is .
+ ///
+ public IServiceProvider CreateServiceProvider(TConfigurator containerBuilder) => CreateServiceProvider(containerBuilder.RejectIf().IsNull(nameof(containerBuilder)), ApplicationConfiguration);
+
+ ///
+ /// Creates an .
+ ///
+ ///
+ /// A source configurator.
+ ///
+ ///
+ /// Configuration information for the application.
+ ///
+ ///
+ /// An .
+ ///
+ protected abstract IServiceProvider CreateServiceProvider(TConfigurator configurator, IConfiguration applicationConfiguration);
+
+ ///
+ /// Prepares a newly-created instance.
+ ///
+ ///
+ /// The configurator to prepare.
+ ///
+ ///
+ /// A collection of services.
+ ///
+ protected abstract void PrepareConfigurator(TConfigurator configurator, IServiceCollection services);
+
+ ///
+ /// Represents configuration information for the application.
+ ///
+ protected readonly IConfiguration ApplicationConfiguration;
+ }
+
///
/// Provides an extension point for creating a container specific builder and an .
///
diff --git a/src/RapidField.SolidInstruments.Messaging.Autofac.Asb/Extensions/ContainerBuilderExtensions.cs b/src/RapidField.SolidInstruments.Messaging.Autofac.Asb/Extensions/ContainerBuilderExtensions.cs
index 49fa90c8..21df5488 100644
--- a/src/RapidField.SolidInstruments.Messaging.Autofac.Asb/Extensions/ContainerBuilderExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.Autofac.Asb/Extensions/ContainerBuilderExtensions.cs
@@ -56,11 +56,11 @@ public static void RegisterSupportingTypesForAzureServiceBusMessaging(this Conta
}
return new ServiceBusConnection(serviceBusConnectionString);
- }).IfNotRegistered(typeof(ServiceBusConnection)).AsSelf().InstancePerLifetimeScope();
+ }).IfNotRegistered(typeof(ServiceBusConnection)).AsSelf().SingleInstance();
- target.RegisterType().IfNotRegistered(typeof(AzureServiceBusMessageAdapter)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(AzureServiceBusClientFactory)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(AzureServiceBusTransmittingFacade)).As().AsSelf().InstancePerLifetimeScope();
+ target.RegisterType().IfNotRegistered(typeof(AzureServiceBusMessageAdapter)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(AzureServiceBusClientFactory)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(AzureServiceBusTransmittingFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(AzureServiceBusListeningFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(AzureServiceBusRequestingFacade)).As().AsSelf().SingleInstance();
}
diff --git a/src/RapidField.SolidInstruments.Messaging.Autofac.Rmq/Extensions/ContainerBuilderExtensions.cs b/src/RapidField.SolidInstruments.Messaging.Autofac.Rmq/Extensions/ContainerBuilderExtensions.cs
index 14ef4e14..ee63f715 100644
--- a/src/RapidField.SolidInstruments.Messaging.Autofac.Rmq/Extensions/ContainerBuilderExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.Autofac.Rmq/Extensions/ContainerBuilderExtensions.cs
@@ -222,9 +222,9 @@ private static void RegisterSupportingTypesForRabbitMqMessaging(this ContainerBu
target.RegisterApplicationConfiguration(applicationConfiguration);
target.RegisterInstance(transport).IfNotRegistered(typeof(RabbitMqMessageTransport)).AsSelf().SingleInstance();
target.RegisterInstance(transport.CreateConnection()).IfNotRegistered(typeof(IMessageTransportConnection)).AsSelf().SingleInstance();
- target.RegisterType().IfNotRegistered(typeof(RabbitMqMessageAdapter)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(RabbitMqClientFactory)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(RabbitMqTransmittingFacade)).As().AsSelf().InstancePerLifetimeScope();
+ target.RegisterType().IfNotRegistered(typeof(RabbitMqMessageAdapter)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(RabbitMqClientFactory)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(RabbitMqTransmittingFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(RabbitMqListeningFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(RabbitMqRequestingFacade)).As().AsSelf().SingleInstance();
}
diff --git a/src/RapidField.SolidInstruments.Messaging.Autofac/Extensions/ContainerBuilderExtensions.cs b/src/RapidField.SolidInstruments.Messaging.Autofac/Extensions/ContainerBuilderExtensions.cs
index 788d6527..cc82ff40 100644
--- a/src/RapidField.SolidInstruments.Messaging.Autofac/Extensions/ContainerBuilderExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.Autofac/Extensions/ContainerBuilderExtensions.cs
@@ -587,9 +587,9 @@ public static void RegisterSupportingTypesForInMemoryMessaging(this ContainerBui
{
target.RegisterInstance(MessageTransport.Instance).IfNotRegistered(typeof(IMessageTransport)).SingleInstance();
target.RegisterInstance(MessageTransport.Instance.CreateConnection()).IfNotRegistered(typeof(IMessageTransportConnection)).SingleInstance();
- target.RegisterType().IfNotRegistered(typeof(InMemoryMessageAdapter)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(InMemoryClientFactory)).As>().AsSelf().InstancePerLifetimeScope();
- target.RegisterType().IfNotRegistered(typeof(InMemoryTransmittingFacade)).As().AsSelf().InstancePerLifetimeScope();
+ target.RegisterType().IfNotRegistered(typeof(InMemoryMessageAdapter)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(InMemoryClientFactory)).As>().AsSelf().SingleInstance();
+ target.RegisterType().IfNotRegistered(typeof(InMemoryTransmittingFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(InMemoryListeningFacade)).As().AsSelf().SingleInstance();
target.RegisterType().IfNotRegistered(typeof(InMemoryRequestingFacade)).As().AsSelf().SingleInstance();
}
diff --git a/src/RapidField.SolidInstruments.Messaging.AzureServiceBus/RapidField.SolidInstruments.Messaging.AzureServiceBus.csproj b/src/RapidField.SolidInstruments.Messaging.AzureServiceBus/RapidField.SolidInstruments.Messaging.AzureServiceBus.csproj
index 46e5ba56..396c6763 100644
--- a/src/RapidField.SolidInstruments.Messaging.AzureServiceBus/RapidField.SolidInstruments.Messaging.AzureServiceBus.csproj
+++ b/src/RapidField.SolidInstruments.Messaging.AzureServiceBus/RapidField.SolidInstruments.Messaging.AzureServiceBus.csproj
@@ -37,7 +37,7 @@ Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in
-
+
diff --git a/src/RapidField.SolidInstruments.Messaging.DotNetNative.Asb/Extensions/IServiceCollectionExtensions.cs b/src/RapidField.SolidInstruments.Messaging.DotNetNative.Asb/Extensions/IServiceCollectionExtensions.cs
index b20e33b9..f68f4d6a 100644
--- a/src/RapidField.SolidInstruments.Messaging.DotNetNative.Asb/Extensions/IServiceCollectionExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.DotNetNative.Asb/Extensions/IServiceCollectionExtensions.cs
@@ -51,7 +51,7 @@ public static IServiceCollection AddSupportingTypesForAzureServiceBusMessaging(t
target.AddApplicationConfiguration(applicationConfiguration);
_ = connectionStringConfigurationKeyName.RejectIf().IsNullOrEmpty(nameof(connectionStringConfigurationKeyName));
- target.TryAddScoped((serviceProvider) =>
+ target.TryAddSingleton((serviceProvider) =>
{
var configuration = serviceProvider.GetService();
var serviceBusConnectionString = configuration.GetConnectionString(connectionStringConfigurationKeyName)?.Trim();
@@ -64,12 +64,12 @@ public static IServiceCollection AddSupportingTypesForAzureServiceBusMessaging(t
return new ServiceBusConnection(serviceBusConnectionString);
});
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
diff --git a/src/RapidField.SolidInstruments.Messaging.DotNetNative.Rmq/Extensions/IServiceCollectionExtensions.cs b/src/RapidField.SolidInstruments.Messaging.DotNetNative.Rmq/Extensions/IServiceCollectionExtensions.cs
index 3980db06..2b432e84 100644
--- a/src/RapidField.SolidInstruments.Messaging.DotNetNative.Rmq/Extensions/IServiceCollectionExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.DotNetNative.Rmq/Extensions/IServiceCollectionExtensions.cs
@@ -245,12 +245,12 @@ private static IServiceCollection AddSupportingTypesForRabbitMqMessaging(this IS
target.AddApplicationConfiguration(applicationConfiguration);
target.TryAddSingleton(transport);
target.TryAddSingleton(transport.CreateConnection());
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
diff --git a/src/RapidField.SolidInstruments.Messaging.DotNetNative/Extensions/IServiceCollectionExtensions.cs b/src/RapidField.SolidInstruments.Messaging.DotNetNative/Extensions/IServiceCollectionExtensions.cs
index 5a0852f3..fdfc1bbb 100644
--- a/src/RapidField.SolidInstruments.Messaging.DotNetNative/Extensions/IServiceCollectionExtensions.cs
+++ b/src/RapidField.SolidInstruments.Messaging.DotNetNative/Extensions/IServiceCollectionExtensions.cs
@@ -673,12 +673,12 @@ public static IServiceCollection AddSupportingTypesForInMemoryMessaging(this ISe
{
target.TryAddSingleton(MessageTransport.Instance);
target.TryAddSingleton(MessageTransport.Instance.CreateConnection());
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped>((serviceProvider) => serviceProvider.GetService());
- target.TryAddScoped();
- target.TryAddScoped((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton>((serviceProvider) => serviceProvider.GetService());
+ target.TryAddSingleton();
+ target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
target.TryAddSingleton((serviceProvider) => serviceProvider.GetService());
target.TryAddSingleton();
diff --git a/src/RapidField.SolidInstruments.Service/RapidField.SolidInstruments.Service.csproj b/src/RapidField.SolidInstruments.Service/RapidField.SolidInstruments.Service.csproj
index 051f33c0..aa42eb1b 100644
--- a/src/RapidField.SolidInstruments.Service/RapidField.SolidInstruments.Service.csproj
+++ b/src/RapidField.SolidInstruments.Service/RapidField.SolidInstruments.Service.csproj
@@ -36,6 +36,12 @@ Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in
+
+
+
+
+
+
diff --git a/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs b/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs
index 1312c513..0a12fe11 100644
--- a/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs
+++ b/src/RapidField.SolidInstruments.Service/ServiceExecutor.cs
@@ -8,7 +8,9 @@
using RapidField.SolidInstruments.Core.Extensions;
using RapidField.SolidInstruments.InversionOfControl;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Threading;
namespace RapidField.SolidInstruments.Service
@@ -151,12 +153,28 @@ public void Execute(String[] commandLineArguments)
///
/// Builds the application configuration for the service.
///
+ ///
+ /// The default implementation of the this method adds:
+ /// - environment variables with prefixes matching any of ,
+ /// - all command line arguments supplied to and
+ /// - the appsettings.json file in the root application path.
+ ///
///
/// An object that is used to build the configuration.
///
protected virtual void BuildConfiguration(IConfigurationBuilder configurationBuilder)
{
- return;
+ foreach (var prefix in EnvironmentVariableConfigurationPrefixes)
+ {
+ _ = configurationBuilder.AddEnvironmentVariables(prefix);
+ }
+
+ if (CommandLineArguments.IsNullOrEmpty() == false)
+ {
+ _ = configurationBuilder.AddCommandLine(CommandLineArguments);
+ }
+
+ _ = configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile(DefaultAppSettingsJsonFileName);
}
///
@@ -275,6 +293,13 @@ internal IServiceExecutionLifetime ExecutionLifetime
///
protected virtual String CopyrightNotice => null;
+ ///
+ /// When overridden by a derived class, gets a collection of textual prefixes which are used by
+ /// to find and add environment variables to
+ /// .
+ ///
+ protected virtual IEnumerable EnvironmentVariableConfigurationPrefixes => Array.Empty();
+
///
/// When overridden by a derived class, gets a product name associated with the service which is written to the console at
/// the start of service execution.
@@ -308,6 +333,13 @@ protected IReferenceManager ReferenceManager
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal String[] CommandLineArguments;
+ ///
+ /// Represents the default JSON settings file name which is used by
+ /// to add file-based configuration to .
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private const String DefaultAppSettingsJsonFileName = "appsettings.json";
+
///
/// Represents lazily-initialized configuration information for the service.
///
diff --git a/src/RapidField.SolidInstruments.Web.Autofac/AssemblyAttributes.cs b/src/RapidField.SolidInstruments.Web.Autofac/AssemblyAttributes.cs
new file mode 100644
index 00000000..a32e4acd
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.Autofac/AssemblyAttributes.cs
@@ -0,0 +1,7 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using System.Runtime.CompilerServices;
+
+[assembly: DisablePrivateReflection()]
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.Autofac/AutofacWebExecutor.cs b/src/RapidField.SolidInstruments.Web.Autofac/AutofacWebExecutor.cs
new file mode 100644
index 00000000..949a409c
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.Autofac/AutofacWebExecutor.cs
@@ -0,0 +1,48 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Autofac;
+using RapidField.SolidInstruments.Core;
+using RapidField.SolidInstruments.InversionOfControl;
+using RapidField.SolidInstruments.InversionOfControl.Autofac;
+using System;
+
+namespace RapidField.SolidInstruments.Web.Autofac
+{
+ ///
+ /// Prepares for and performs execution of a web application using Autofac IoC tooling.
+ ///
+ ///
+ /// The type of the package that configures the dependency engine.
+ ///
+ public abstract class AutofacWebExecutor : WebExecutor
+ where TDependencyPackage : class, IDependencyPackage, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The name of the web application.
+ ///
+ ///
+ /// is empty.
+ ///
+ ///
+ /// is .
+ ///
+ protected AutofacWebExecutor(String applicationName)
+ : base(applicationName)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.Autofac/Extensions/ContainerBuilderExtensions.cs b/src/RapidField.SolidInstruments.Web.Autofac/Extensions/ContainerBuilderExtensions.cs
new file mode 100644
index 00000000..dbe79916
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.Autofac/Extensions/ContainerBuilderExtensions.cs
@@ -0,0 +1,16 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Autofac;
+
+namespace RapidField.SolidInstruments.Web.Autofac.Extensions
+{
+ ///
+ /// Extends the class with inversion of control features to support web application
+ /// abstractions.
+ ///
+ public static class ContainerBuilderExtensions
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.Autofac/README.md b/src/RapidField.SolidInstruments.Web.Autofac/README.md
new file mode 100644
index 00000000..afb2636d
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.Autofac/README.md
@@ -0,0 +1,57 @@
+
+
+[![Solid Instruments](../../SolidInstruments.Logo.Color.Transparent.500w.png)](../../README.md)
+
+![Web](../../doc/images/Label.Web.300w.png)
+- - -
+
+# RapidField.SolidInstruments.Web.Autofac
+
+This document describes the purpose of the [`RapidField.SolidInstruments.Web`]() library and offers guidance with respect to licensing, installation and usage.
+
+## Features
+
+This library exposes the [**Autofac**](https://autofac.org/) IoC integration for the **Solid Instruments** web application abstractions.
+
+## License
+
+[![License](https://img.shields.io/github/license/rapidfield/solid-instruments?style=flat&color=lightseagreen&label=license&logo=open-access&logoColor=lightgrey)](../../LICENSE.txt)
+
+**Solid Instruments** is [MIT-licensed](https://en.wikipedia.org/wiki/MIT_License). Review the [license terms](../../LICENSE.txt) for more information.
+
+## Documentation
+
+[![Documentation](https://img.shields.io/badge/documentation-website-tan?style=flat&logo=buffer&logoColor=lightgrey)](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.Autofac.html)
+
+Check out the [**API Reference**](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.Autofac.html) for usage examples and reference documentation.
+
+## Installation
+
+[![Version](https://img.shields.io/nuget/vpre/RapidField.SolidInstruments.Web.Autofac?style=flat&color=blue&label=version&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web.Autofac)
+[![Downloads](https://img.shields.io/nuget/dt/RapidField.SolidInstruments.Web.Autofac?style=flat&color=blue&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web.Autofac)
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.Autofac
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.Autofac
+```
+
+
+
+- - -
+
+
+
+[![RapidField](../../RapidField.Logo.Color.Black.Transparent.200w.png)](https://www.rapidfield.com)
+
+###### Copyright (c) RapidField LLC. All rights reserved. "RapidField" and "Solid Instruments" are trademarks of RapidField LLC.
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.Autofac/RapidField.SolidInstruments.Web.Autofac.csproj b/src/RapidField.SolidInstruments.Web.Autofac/RapidField.SolidInstruments.Web.Autofac.csproj
new file mode 100644
index 00000000..11bdb4d9
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.Autofac/RapidField.SolidInstruments.Web.Autofac.csproj
@@ -0,0 +1,50 @@
+
+
+
+
+ Solid Instruments contributors
+ RapidField
+ Copyright (c) RapidField LLC. All rights reserved.
+ Solid Instruments
+ This library exposes the Autofac IoC integration for the Solid Instruments web application abstractions.
+ $(BuildVersion)
+ netstandard2.1
+ latest
+ git
+ https://github.com/rapidfield/solid-instruments
+ true
+ true
+ LICENSE.txt
+ https://www.solidinstruments.com
+ Icon.Web.128w.png
+ solid-instruments;web;web-application;inversion-of-control;ioc;dependency-injection;di;autofac
+
+
+ bin\Debug\netstandard2.1\RapidField.SolidInstruments.Web.Autofac.xml
+ true
+
+
+
+ bin\Release\netstandard2.1\RapidField.SolidInstruments.Web.Autofac.xml
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.DotNetNative/AssemblyAttributes.cs b/src/RapidField.SolidInstruments.Web.DotNetNative/AssemblyAttributes.cs
new file mode 100644
index 00000000..a32e4acd
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.DotNetNative/AssemblyAttributes.cs
@@ -0,0 +1,7 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using System.Runtime.CompilerServices;
+
+[assembly: DisablePrivateReflection()]
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.DotNetNative/DotNetNativeWebExecutor.cs b/src/RapidField.SolidInstruments.Web.DotNetNative/DotNetNativeWebExecutor.cs
new file mode 100644
index 00000000..2eb2af88
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.DotNetNative/DotNetNativeWebExecutor.cs
@@ -0,0 +1,48 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.Extensions.DependencyInjection;
+using RapidField.SolidInstruments.Core;
+using RapidField.SolidInstruments.InversionOfControl;
+using RapidField.SolidInstruments.InversionOfControl.DotNetNative;
+using System;
+
+namespace RapidField.SolidInstruments.Web.DotNetNative
+{
+ ///
+ /// Prepares for and performs execution of a web application using native .NET IoC tooling.
+ ///
+ ///
+ /// The type of the package that configures the dependency engine.
+ ///
+ public abstract class DotNetNativeWebExecutor : WebExecutor
+ where TDependencyPackage : class, IDependencyPackage, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The name of the web application.
+ ///
+ ///
+ /// is empty.
+ ///
+ ///
+ /// is .
+ ///
+ protected DotNetNativeWebExecutor(String applicationName)
+ : base(applicationName)
+ {
+ return;
+ }
+
+ ///
+ /// Releases all resources consumed by the current .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing) => base.Dispose(disposing);
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.DotNetNative/Extensions/IServiceCollectionExtensions.cs b/src/RapidField.SolidInstruments.Web.DotNetNative/Extensions/IServiceCollectionExtensions.cs
new file mode 100644
index 00000000..81671c50
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.DotNetNative/Extensions/IServiceCollectionExtensions.cs
@@ -0,0 +1,16 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.Extensions.DependencyInjection;
+
+namespace RapidField.SolidInstruments.Command.DotNetNative.Extensions
+{
+ ///
+ /// Extends the interface with native .NET inversion of control features to support web
+ /// application abstractions.
+ ///
+ public static class IServiceCollectionExtensions
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.DotNetNative/README.md b/src/RapidField.SolidInstruments.Web.DotNetNative/README.md
new file mode 100644
index 00000000..8f75e3ab
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.DotNetNative/README.md
@@ -0,0 +1,57 @@
+
+
+[![Solid Instruments](../../SolidInstruments.Logo.Color.Transparent.500w.png)](../../README.md)
+
+![Web](../../doc/images/Label.Web.300w.png)
+- - -
+
+# RapidField.SolidInstruments.Web.DotNetNative
+
+This document describes the purpose of the [`RapidField.SolidInstruments.Web`]() library and offers guidance with respect to licensing, installation and usage.
+
+## Features
+
+This library exposes the native .NET IoC integration for the **Solid Instruments** web application abstractions.
+
+## License
+
+[![License](https://img.shields.io/github/license/rapidfield/solid-instruments?style=flat&color=lightseagreen&label=license&logo=open-access&logoColor=lightgrey)](../../LICENSE.txt)
+
+**Solid Instruments** is [MIT-licensed](https://en.wikipedia.org/wiki/MIT_License). Review the [license terms](../../LICENSE.txt) for more information.
+
+## Documentation
+
+[![Documentation](https://img.shields.io/badge/documentation-website-tan?style=flat&logo=buffer&logoColor=lightgrey)](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.DotNetNative.html)
+
+Check out the [**API Reference**](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.DotNetNative.html) for usage examples and reference documentation.
+
+## Installation
+
+[![Version](https://img.shields.io/nuget/vpre/RapidField.SolidInstruments.Web.DotNetNative?style=flat&color=blue&label=version&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web.DotNetNative)
+[![Downloads](https://img.shields.io/nuget/dt/RapidField.SolidInstruments.Web.DotNetNative?style=flat&color=blue&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web.DotNetNative)
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web.DotNetNative
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web.DotNetNative
+```
+
+
+
+- - -
+
+
+
+[![RapidField](../../RapidField.Logo.Color.Black.Transparent.200w.png)](https://www.rapidfield.com)
+
+###### Copyright (c) RapidField LLC. All rights reserved. "RapidField" and "Solid Instruments" are trademarks of RapidField LLC.
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web.DotNetNative/RapidField.SolidInstruments.Web.DotNetNative.csproj b/src/RapidField.SolidInstruments.Web.DotNetNative/RapidField.SolidInstruments.Web.DotNetNative.csproj
new file mode 100644
index 00000000..9248b657
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web.DotNetNative/RapidField.SolidInstruments.Web.DotNetNative.csproj
@@ -0,0 +1,50 @@
+
+
+
+
+ Solid Instruments contributors
+ RapidField
+ Copyright (c) RapidField LLC. All rights reserved.
+ Solid Instruments
+ This library exposes the native .NET IoC integration for the Solid Instruments web application abstractions.
+ $(BuildVersion)
+ netstandard2.1
+ latest
+ git
+ https://github.com/rapidfield/solid-instruments
+ true
+ true
+ LICENSE.txt
+ https://www.solidinstruments.com
+ Icon.Web.128w.png
+ solid-instruments;web;web-application;inversion-of-control;ioc;dependency-injection;di
+
+
+ bin\Debug\netstandard2.1\RapidField.SolidInstruments.Web.DotNetNative.xml
+ true
+
+
+
+ bin\Release\netstandard2.1\RapidField.SolidInstruments.Web.DotNetNative.xml
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/AssemblyAttributes.cs b/src/RapidField.SolidInstruments.Web/AssemblyAttributes.cs
new file mode 100644
index 00000000..a32e4acd
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/AssemblyAttributes.cs
@@ -0,0 +1,7 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using System.Runtime.CompilerServices;
+
+[assembly: DisablePrivateReflection()]
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/IWebExecutor.cs b/src/RapidField.SolidInstruments.Web/IWebExecutor.cs
new file mode 100644
index 00000000..823e56c7
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/IWebExecutor.cs
@@ -0,0 +1,42 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using RapidField.SolidInstruments.Core;
+using System;
+
+namespace RapidField.SolidInstruments.Web
+{
+ ///
+ /// Prepares for and performs execution of a web application.
+ ///
+ public interface IWebExecutor : IInstrument
+ {
+ ///
+ /// Begins execution of the web application.
+ ///
+ ///
+ /// An exception was raised during execution of the web application.
+ ///
+ public void Execute();
+
+ ///
+ /// Begins execution of the web application.
+ ///
+ ///
+ /// Command line arguments that are provided at runtime, if any.
+ ///
+ ///
+ /// An exception was raised during execution of the web application.
+ ///
+ public void Execute(String[] commandLineArguments);
+
+ ///
+ /// Gets the name of the web application.
+ ///
+ public String ApplicationName
+ {
+ get;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/README.md b/src/RapidField.SolidInstruments.Web/README.md
new file mode 100644
index 00000000..66d3e9bc
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/README.md
@@ -0,0 +1,57 @@
+
+
+[![Solid Instruments](../../SolidInstruments.Logo.Color.Transparent.500w.png)](../../README.md)
+
+![Web](../../doc/images/Label.Web.300w.png)
+- - -
+
+# RapidField.SolidInstruments.Web
+
+This document describes the purpose of the [`RapidField.SolidInstruments.Web`]() library and offers guidance with respect to licensing, installation and usage.
+
+## Features
+
+This library exposes types that simplify web application design.
+
+## License
+
+[![License](https://img.shields.io/github/license/rapidfield/solid-instruments?style=flat&color=lightseagreen&label=license&logo=open-access&logoColor=lightgrey)](../../LICENSE.txt)
+
+**Solid Instruments** is [MIT-licensed](https://en.wikipedia.org/wiki/MIT_License). Review the [license terms](../../LICENSE.txt) for more information.
+
+## Documentation
+
+[![Documentation](https://img.shields.io/badge/documentation-website-tan?style=flat&logo=buffer&logoColor=lightgrey)](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.html)
+
+Check out the [**API Reference**](https://www.solidinstruments.com/api/RapidField.SolidInstruments.Web.html) for usage examples and reference documentation.
+
+## Installation
+
+[![Version](https://img.shields.io/nuget/vpre/RapidField.SolidInstruments.Web?style=flat&color=blue&label=version&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web)
+[![Downloads](https://img.shields.io/nuget/dt/RapidField.SolidInstruments.Web?style=flat&color=blue&logo=nuget&logoColor=lightgrey)](https://www.nuget.org/packages/RapidField.SolidInstruments.Web)
+
+This library is available via [**NuGet**](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio). Use one of the commands below to download and install the library and all of its dependencies.
+
+###### .NET CLI
+
+```shell
+dotnet add package RapidField.SolidInstruments.Web
+```
+
+###### NuGet Package Manager
+
+```shell
+Install-Package RapidField.SolidInstruments.Web
+```
+
+
+
+- - -
+
+
+
+[![RapidField](../../RapidField.Logo.Color.Black.Transparent.200w.png)](https://www.rapidfield.com)
+
+###### Copyright (c) RapidField LLC. All rights reserved. "RapidField" and "Solid Instruments" are trademarks of RapidField LLC.
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/RapidField.SolidInstruments.Web.csproj b/src/RapidField.SolidInstruments.Web/RapidField.SolidInstruments.Web.csproj
new file mode 100644
index 00000000..012608a1
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/RapidField.SolidInstruments.Web.csproj
@@ -0,0 +1,48 @@
+
+
+
+
+ Solid Instruments contributors
+ RapidField
+ Copyright (c) RapidField LLC. All rights reserved.
+ Solid Instruments
+ This library exposes types that simplify web application design.
+ $(BuildVersion)
+ netstandard2.1
+ latest
+ git
+ https://github.com/rapidfield/solid-instruments
+ true
+ true
+ LICENSE.txt
+ https://www.solidinstruments.com
+ Icon.Web.128w.png
+ solid-instruments;web;web-application
+
+
+ bin\Debug\netstandard2.1\RapidField.SolidInstruments.Web.xml
+ true
+
+
+
+ bin\Release\netstandard2.1\RapidField.SolidInstruments.Web.xml
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/WebExecutionException.cs b/src/RapidField.SolidInstruments.Web/WebExecutionException.cs
new file mode 100644
index 00000000..f94823f8
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/WebExecutionException.cs
@@ -0,0 +1,50 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using System;
+
+namespace RapidField.SolidInstruments.Web
+{
+ ///
+ /// Represents an exception that is raised during web application execution.
+ ///
+ public class WebExectuionException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public WebExectuionException()
+ : base()
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The error message that explains the reason for the exception.
+ ///
+ public WebExectuionException(String message)
+ : base(message)
+ {
+ return;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The error message that explains the reason for the exception.
+ ///
+ ///
+ /// The exception that is the cause of the current exception.
+ ///
+ public WebExectuionException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/RapidField.SolidInstruments.Web/WebExecutor.cs b/src/RapidField.SolidInstruments.Web/WebExecutor.cs
new file mode 100644
index 00000000..ad48d54a
--- /dev/null
+++ b/src/RapidField.SolidInstruments.Web/WebExecutor.cs
@@ -0,0 +1,409 @@
+// =================================================================================================================================
+// Copyright (c) RapidField LLC. Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+// =================================================================================================================================
+
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using RapidField.SolidInstruments.Core;
+using RapidField.SolidInstruments.Core.ArgumentValidation;
+using RapidField.SolidInstruments.Core.Extensions;
+using RapidField.SolidInstruments.InversionOfControl;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using WebHostInitializer = Microsoft.AspNetCore.WebHost;
+
+namespace RapidField.SolidInstruments.Web
+{
+ ///
+ /// Prepares for and performs execution of a web application.
+ ///
+ ///
+ /// is the default implementation of
+ /// .
+ ///
+ ///
+ /// The type of the package that configures the dependency engine.
+ ///
+ ///
+ /// The type of the object that configures the dependency container.
+ ///
+ ///
+ /// The type of the dependency engine that is produced by the dependency package.
+ ///
+ public abstract class WebExecutor : Instrument, IWebExecutor
+ where TDependencyPackage : class, IDependencyPackage, new()
+ where TDependencyConfigurator : class, new()
+ where TDependencyEngine : class, IDependencyEngine
+ {
+ ///
+ /// Initializes a new instance of the
+ /// class.
+ ///
+ ///
+ /// The name of the web application.
+ ///
+ ///
+ /// is empty.
+ ///
+ ///
+ /// is .
+ ///
+ protected WebExecutor(String applicationName)
+ : base()
+ {
+ ApplicationName = applicationName.Trim().RejectIf().IsNullOrEmpty(nameof(applicationName));
+ CommandLineArguments = null;
+ LazyApplicationConfiguration = new Lazy(CreateApplicationConfiguration, LazyThreadSafetyMode.ExecutionAndPublication);
+ LazyDependencyEngine = new Lazy(CreateDependencyEngine, LazyThreadSafetyMode.ExecutionAndPublication);
+ LazyRootDependencyScope = new Lazy(DependencyEngine.Container.CreateScope, LazyThreadSafetyMode.ExecutionAndPublication);
+ LazyWebHost = new Lazy(CreateWebHost, LazyThreadSafetyMode.ExecutionAndPublication);
+ ReferenceManager = new ReferenceManager();
+ }
+
+ ///
+ /// Begins execution of the web application.
+ ///
+ ///
+ /// An exception was raised during execution of the web application.
+ ///
+ public void Execute() => Execute(Array.Empty());
+
+ ///
+ /// Begins execution of the web application.
+ ///
+ ///
+ /// Command line arguments that are provided at runtime, if any.
+ ///
+ ///
+ /// An exception was raised during execution of the web application.
+ ///
+ public void Execute(String[] commandLineArguments)
+ {
+ CommandLineArguments = commandLineArguments ?? Array.Empty();
+
+ try
+ {
+ var productName = ProductName?.Trim();
+ var applicationName = ApplicationName?.Trim();
+ var copyrightNotice = CopyrightNotice?.Trim();
+
+ if (productName.IsNullOrEmpty() == false)
+ {
+ Console.WriteLine(productName);
+ }
+
+ if (applicationName.IsNullOrEmpty() == false)
+ {
+ Console.WriteLine(applicationName);
+ }
+
+ if (copyrightNotice.IsNullOrEmpty() == false)
+ {
+ Console.WriteLine(copyrightNotice);
+ }
+
+ Console.WriteLine($"{Environment.NewLine}Web application execution starting.");
+
+ try
+ {
+ var webHost = WebHost; // Do not move this line.
+
+ using (var dependencyScope = CreateDependencyScope())
+ {
+ Execute(webHost, dependencyScope, ApplicationConfiguration, CommandLineArguments);
+ }
+ }
+ catch (WebExectuionException)
+ {
+ throw;
+ }
+ catch (Exception exception)
+ {
+ throw new WebExectuionException($"An exception was raised during execution of the web application: \"{ApplicationName}\". See inner exception.", exception);
+ }
+ }
+ catch (WebExectuionException exception)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"{exception.Message} : {exception.StackTrace}{Environment.NewLine}");
+ Console.ResetColor();
+ throw;
+ }
+ finally
+ {
+ Console.WriteLine("Web application execution finished.");
+ }
+ }
+
+ ///
+ /// Converts the value of the current
+ /// to its equivalent string
+ /// representation.
+ ///
+ ///
+ /// A string representation of the current
+ /// .
+ ///
+ public override String ToString() => $"{{ \"{nameof(ApplicationName)}\": \"{ApplicationName}\" }}";
+
+ ///
+ /// Builds the application configuration for the web application.
+ ///
+ ///
+ /// The default implementation of the this method adds:
+ /// - environment variables with prefixes matching any of ,
+ /// - all command line arguments supplied to and
+ /// - the appsettings.json file in the root application path.
+ ///
+ ///
+ /// An object that is used to build the configuration.
+ ///
+ protected virtual void BuildConfiguration(IConfigurationBuilder configurationBuilder)
+ {
+ foreach (var prefix in EnvironmentVariableConfigurationPrefixes)
+ {
+ _ = configurationBuilder.AddEnvironmentVariables(prefix);
+ }
+
+ if (CommandLineArguments.IsNullOrEmpty() == false)
+ {
+ _ = configurationBuilder.AddCommandLine(CommandLineArguments);
+ }
+
+ _ = configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile(DefaultAppSettingsJsonFileName);
+ }
+
+ ///
+ /// Configures the application's request pipeline.
+ ///
+ ///
+ /// An object that configures the application's request pipeline.
+ ///
+ ///
+ /// Configuration information for the web application.
+ ///
+ ///
+ /// Command line arguments that are provided at runtime, if any.
+ ///
+ protected virtual void ConfigureApplication(IApplicationBuilder application, IConfiguration applicationConfiguration, String[] commandLineArguments)
+ {
+ return;
+ }
+
+ ///
+ /// Creates a new dependency scope.
+ ///
+ ///
+ /// A new dependency scope.
+ ///
+ ///
+ /// An exception was raised while attempting to create the scope.
+ ///
+ ///
+ /// The object is disposed.
+ ///
+ protected IDependencyScope CreateDependencyScope() => RootDependencyScope.CreateChildScope();
+
+ ///
+ /// Releases all resources consumed by the current
+ /// .
+ ///
+ ///
+ /// A value indicating whether or not managed resources should be released.
+ ///
+ protected override void Dispose(Boolean disposing)
+ {
+ try
+ {
+ if (disposing)
+ {
+ LazyRootDependencyScope.Dispose();
+ LazyDependencyEngine.Dispose();
+ ReferenceManager.Dispose();
+ }
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+
+ ///
+ /// Begins execution of the web application.
+ ///
+ ///
+ /// A configured web host.
+ ///
+ ///
+ /// A scope that is used to resolve web application dependencies.
+ ///
+ ///
+ /// Configuration information for the web application.
+ ///
+ ///
+ /// Command line arguments that are provided at runtime, if any.
+ ///
+ protected virtual void Execute(IWebHost webHost, IDependencyScope dependencyScope, IConfiguration applicationConfiguration, String[] commandLineArguments) => webHost.Start();
+
+ ///
+ /// Creates configuration information for the web application.
+ ///
+ ///
+ /// Configuration information for the web application.
+ ///
+ [DebuggerHidden]
+ private IConfiguration CreateApplicationConfiguration()
+ {
+ var configurationBuilder = new ConfigurationBuilder();
+ BuildConfiguration(configurationBuilder);
+ return configurationBuilder.Build();
+ }
+
+ ///
+ /// Creates the dependency engine for the web application.
+ ///
+ ///
+ /// The dependency engine for the web application.
+ ///
+ [DebuggerHidden]
+ private IDependencyEngine CreateDependencyEngine()
+ {
+ var dependencyPackage = new TDependencyPackage();
+ return dependencyPackage.CreateEngine(ApplicationConfiguration, ServiceDescriptors);
+ }
+
+ ///
+ /// Creates the web application host.
+ ///
+ ///
+ /// The web application host.
+ ///
+ [DebuggerHidden]
+ private IWebHost CreateWebHost() => WebHostInitializer.CreateDefaultBuilder()
+ .UseConfiguration(ApplicationConfiguration)
+ .Configure(application =>
+ {
+ ConfigureApplication(application, ApplicationConfiguration, CommandLineArguments);
+ })
+ .ConfigureServices(services =>
+ {
+ foreach (var serviceDescritor in services)
+ {
+ ServiceDescriptors.TryAdd(serviceDescritor);
+ }
+ })
+ .Configure(application =>
+ {
+ application.ApplicationServices = DependencyEngine.Provider;
+ })
+ .Build();
+
+ ///
+ /// Gets the name of the web application.
+ ///
+ public String ApplicationName
+ {
+ get;
+ }
+
+ ///
+ /// Gets configuration information for the web application.
+ ///
+ protected IConfiguration ApplicationConfiguration => LazyApplicationConfiguration.Value;
+
+ ///
+ /// When overridden by a derived class, gets a copyright notice which is written to the console at the start of web
+ /// application execution.
+ ///
+ protected virtual String CopyrightNotice => null;
+
+ ///
+ /// When overridden by a derived class, gets a collection of textual prefixes which are used by
+ /// to find and add environment variables to
+ /// .
+ ///
+ protected virtual IEnumerable EnvironmentVariableConfigurationPrefixes => Array.Empty();
+
+ ///
+ /// When overridden by a derived class, gets a product name associated with the web application which is written to the
+ /// console at the start of web application execution.
+ ///
+ protected virtual String ProductName => null;
+
+ ///
+ /// Gets a utility that disposes of the object references that are managed by the current
+ /// .
+ ///
+ protected IReferenceManager ReferenceManager
+ {
+ get;
+ }
+
+ ///
+ /// Gets the dependency engine for the web application.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private IDependencyEngine DependencyEngine => LazyDependencyEngine.Value;
+
+ ///
+ /// Gets the root dependency scope for the web application.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private IDependencyScope RootDependencyScope => LazyRootDependencyScope.Value;
+
+ ///
+ /// Gets the web application host.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private IWebHost WebHost => LazyWebHost.Value;
+
+ ///
+ /// Represents the command line arguments that were provided at runtime, if any.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal String[] CommandLineArguments;
+
+ ///
+ /// Represents the default JSON settings file name which is used by
+ /// to add file-based configuration to .
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private const String DefaultAppSettingsJsonFileName = "appsettings.json";
+
+ ///
+ /// Represents lazily-initialized configuration information for the web application.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Lazy LazyApplicationConfiguration;
+
+ ///
+ /// Represents the lazily-initialized dependency engine for the web application.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Lazy LazyDependencyEngine;
+
+ ///
+ /// Represents the lazily-initialized root dependency scope for the web application.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Lazy LazyRootDependencyScope;
+
+ ///
+ /// Represents the lazily-initialized web application host.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Lazy LazyWebHost;
+
+ ///
+ /// Represents a collection of configured service descriptors.
+ ///
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly IServiceCollection ServiceDescriptors = new ServiceCollection();
+ }
+}
\ No newline at end of file
diff --git a/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs b/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs
index 9f6ffb4f..7f3117e7 100644
--- a/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs
+++ b/test/RapidField.SolidInstruments.Messaging.InMemory.UnitTests/SimulatedMessagingServiceExecutorTests.cs
@@ -51,7 +51,7 @@ private void OnStopping(ICommandMediator mediator)
mediator.Process(new CreateCustomerCommandMessage(new CreateCustomerCommand(smithIndustriesCustomer)));
// Assert.
- Thread.Sleep(6765);
+ Thread.Sleep(10946);
SimulatedServiceState.Customers.Should().HaveCount(2);
// Act.