diff --git a/.build/BuildToolkit.ps1 b/.build/BuildToolkit.ps1
deleted file mode 100644
index 26d22dbf7..000000000
--- a/.build/BuildToolkit.ps1
+++ /dev/null
@@ -1,680 +0,0 @@
-# Tool Versions
-$NunitVersion = "3.12.0";
-$OpenCoverVersion = "4.7.1221";
-$DocFxVersion = "2.58.4";
-$ReportGeneratorVersion = "4.8.13";
-$OpenCoverToCoberturaVersion = "0.3.4";
-
-# Folder Pathes
-$RootPath = $MyInvocation.PSScriptRoot;
-$BuildTools = "$RootPath\packages";
-
-# Artifacts
-$ArtifactsDir = "$RootPath\artifacts";
-
-# Documentation
-$DocumentationDir = "$RootPath\docs";
-$DocumentationArtifcacts = "$ArtifactsDir\Documentation";
-
-# Tests
-$NunitReportsDir = "$ArtifactsDir\Tests";
-$OpenCoverReportsDir = "$ArtifactsDir\Tests"
-$CoberturaReportsDir = "$ArtifactsDir\Tests"
-
-# Nuget
-$NugetConfig = "$RootPath\NuGet.Config";
-$NugetPackageArtifacts = "$ArtifactsDir\Packages";
-
-# Load partial scripts
-. "$PSScriptRoot\Output.ps1";
-
-# Define Tools
-$global:DotNetCli = "dotnet.exe";
-$global:NugetCli = "nuget.exe";
-$global:GitCli = "";
-$global:OpenCoverCli = "$BuildTools\OpenCover.$OpenCoverVersion\tools\OpenCover.Console.exe";
-$global:NunitCli = "$BuildTools\NUnit.ConsoleRunner.$NunitVersion\tools\nunit3-console.exe";
-$global:ReportGeneratorCli = "$BuildTools\ReportGenerator.$ReportGeneratorVersion\tools\net47\ReportGenerator.exe";
-$global:DocFxCli = "$BuildTools\docfx.console.$DocFxVersion\tools\docfx.exe";
-$global:OpenCoverToCoberturaCli = "$BuildTools\OpenCoverToCoberturaConverter.$OpenCoverToCoberturaVersion\tools\OpenCoverToCoberturaConverter.exe";
-
-# Git
-$global:GitCommitHash = "";
-
-# Functions
-function Invoke-Initialize([string]$Version = "1.0.0", [bool]$Cleanup = $False) {
- Write-Step "Initializing BuildToolkit"
-
- # First check the powershell version
- if ($PSVersionTable.PSVersion.Major -lt 5) {
- Write-Host ("The needed major powershell version for this script is 5. Your version: " + ($PSVersionTable.PSVersion.ToString()))
- exit 1;
- }
-
- # Assign git.exe
- $gitCommand = (Get-Command "git.exe" -ErrorAction SilentlyContinue);
- if ($null -eq $gitCommand) {
- Write-Host "Unable to find git.exe in your PATH. Download from https://git-scm.com";
- exit 1;
- }
-
- $global:GitCli = $gitCommand.Path;
-
- # Load Hash
- $global:GitCommitHash = (& $global:GitCli rev-parse HEAD);
- Invoke-ExitCodeCheck $LastExitCode;
-
- # Initialize Folders
- CreateFolderIfNotExists $BuildTools;
- CreateFolderIfNotExists $ArtifactsDir;
-
- # Environment Variable Defaults
- if (-not $env:MORYX_BUILDNUMBER) {
- $env:MORYX_BUILDNUMBER = 0;
- }
-
- if (-not $env:MORYX_BUILD_CONFIG) {
- $env:MORYX_BUILD_CONFIG = "Debug";
- }
-
- if (-not $env:MORYX_BUILD_VERBOSITY) {
- $env:MORYX_BUILD_VERBOSITY = "minimal"
- }
-
- if (-not $env:MORYX_TEST_VERBOSITY) {
- $env:MORYX_TEST_VERBOSITY = "normal"
- }
-
- if (-not $env:MORYX_NUGET_VERBOSITY) {
- $env:MORYX_NUGET_VERBOSITY = "normal"
- }
-
- if (-not $env:MORYX_OPTIMIZE_CODE) {
- $env:MORYX_OPTIMIZE_CODE = $True;
- }
- else {
- if (-not [bool]::TryParse($env:MORYX_OPTIMIZE_CODE, [ref]$env:MORYX_OPTIMIZE_CODE)) {
- $env:MORYX_OPTIMIZE_CODE = $True;
- }
- }
-
- if (-not $env:MORYX_PACKAGE_TARGET) {
- $env:MORYX_PACKAGE_TARGET = "";
- }
-
- if (-not $env:MORYX_PACKAGE_TARGET_V3) {
- $env:MORYX_PACKAGE_TARGET_V3 = "";
- }
-
- if (-not $env:MORYX_ASSEMBLY_VERSION) {
- $env:MORYX_ASSEMBLY_VERSION = $Version;
- }
-
- if (-not $env:MORYX_FILE_VERSION) {
- $env:MORYX_FILE_VERSION = $Version;
- }
-
- if (-not $env:MORYX_INFORMATIONAL_VERSION) {
- $env:MORYX_INFORMATIONAL_VERSION = $Version;
- }
-
- if (-not $env:MORYX_PACKAGE_VERSION) {
- $env:MORYX_PACKAGE_VERSION = $Version;
- }
-
- Set-Version $Version;
-
- # Printing Variables
- Write-Step "Printing global variables"
- Write-Variable "RootPath" $RootPath;
- Write-Variable "DocumentationDir" $DocumentationDir;
- Write-Variable "NunitReportsDir" $NunitReportsDir;
-
- Write-Step "Printing global scope"
- Write-Variable "OpenCoverCli" $global:OpenCoverCli;
- Write-Variable "NUnitCli" $global:NUnitCli;
- Write-Variable "ReportGeneratorCli" $global:ReportGeneratorCli;
- Write-Variable "DocFxCli" $global:DocFxCli;
- Write-Variable "OpenCoverToCoberturaCli" $global:OpenCoverToCoberturaCli;
- Write-Variable "GitCli" $global:GitCli;
- Write-Variable "GitCommitHash" $global:GitCommitHash;
-
- Write-Step "Printing environment variables"
- Write-Variable "MORYX_OPTIMIZE_CODE" $env:MORYX_OPTIMIZE_CODE;
- Write-Variable "MORYX_BUILDNUMBER" $env:MORYX_BUILDNUMBER;
- Write-Variable "MORYX_BUILD_CONFIG" $env:MORYX_BUILD_CONFIG;
- Write-Variable "MORYX_BUILD_VERBOSITY" $env:MORYX_BUILD_VERBOSITY;
- Write-Variable "MORYX_TEST_VERBOSITY" $env:MORYX_TEST_VERBOSITY;
- Write-Variable "MORYX_NUGET_VERBOSITY" $env:MORYX_NUGET_VERBOSITY;
- Write-Variable "MORYX_PACKAGE_TARGET" $env:MORYX_PACKAGE_TARGET;
- Write-Variable "MORYX_PACKAGE_TARGET_V3" $env:MORYX_PACKAGE_TARGET_V3;
-
- Write-Variable "MORYX_ASSEMBLY_VERSION" $env:MORYX_ASSEMBLY_VERSION;
- Write-Variable "MORYX_FILE_VERSION" $env:MORYX_FILE_VERSION;
- Write-Variable "MORYX_INFORMATIONAL_VERSION" $env:MORYX_INFORMATIONAL_VERSION;
- Write-Variable "MORYX_PACKAGE_VERSION" $env:MORYX_PACKAGE_VERSION;
-
-
- # Cleanp
- if ($Cleanup) {
- Write-Step "Cleanup"
-
- Write-Host "Cleaning up repository ..." -ForegroundColor Red;
- & $global:GitCli clean -f -d -x
- Invoke-ExitCodeCheck $LastExitCode;
-
- & $global:GitCli checkout .
- Invoke-ExitCodeCheck $LastExitCode;
- }
-}
-
-function Invoke-Cleanup {
- # Clean up
- Write-Step "Cleaning up repository ...";
- & $global:GitCli clean -f -d -x
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Install-Tool([string]$PackageName, [string]$Version, [string]$TargetExecutable, [string]$OutputDirectory = $BuildTools) {
- if (-not (Test-Path $TargetExecutable)) {
- & $global:NugetCli install $PackageName -version $Version -outputdirectory $OutputDirectory -configfile $NugetConfig
- Invoke-ExitCodeCheck $LastExitCode;
- }
- else {
- Write-Host "$PackageName ($Version) already exists. Do not need to install."
- }
-}
-
-function Invoke-Build([string]$ProjectFile, [string]$Options = "") {
- Write-Step "Building $ProjectFile"
-
- # TODO: maybe we find a better way: currently all packages of all solutions are restored.
- ForEach ($solution in (Get-ChildItem $RootPath -Filter "*.sln")) {
- Write-Host "Restoring Nuget packages of $solution";
-
- & $global:DotNetCli restore $solution --verbosity $env:MORYX_NUGET_VERBOSITY --configfile $NugetConfig;
- Invoke-ExitCodeCheck $LastExitCode;
- }
-
- $additonalOptions = "";
- if (-not [string]::IsNullOrEmpty($Options)) {
- $additonalOptions = ",$Options";
- }
-
- $msbuildParams = "Optimize=" + (&{If($env:MORYX_OPTIMIZE_CODE -eq $True) {"true"} Else {"false"}}) + ",DebugSymbols=true$additonalOptions";
- $buildArgs = "--configuration", "$env:MORYX_BUILD_CONFIG";
- $buildArgs += "--verbosity", $env:MORYX_BUILD_VERBOSITY;
- $buildArgs += "-p:$msbuildParams"
-
- & $global:DotNetCli build $ProjectFile @buildArgs
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-Nunit([string]$SearchPath = $RootPath, [string]$SearchFilter = "*.csproj") {
- $randomIncrement = Get-Random -Minimum 2000 -Maximum 2100
- Write-Step "Running $Name Tests: $SearchPath"
-
- $testProjects = Get-ChildItem $SearchPath -Recurse -Include $SearchFilter
- if ($testProjects.Length -eq 0) {
- Write-Host-Warning "No test projects found!"
- return;
- }
-
- $env:PORT_INCREMENT = $randomIncrement;
-
- if (-not (Test-Path $global:NUnitCli)) {
- Install-Tool "NUnit.Console" $NunitVersion $global:NunitCli;
- }
-
- CreateFolderIfNotExists $NunitReportsDir;
-
- ForEach($testProject in $testProjects ) {
- $projectName = ([System.IO.Path]::GetFileNameWithoutExtension($testProject.Name));
- $testAssembly = [System.IO.Path]::Combine($testProject.DirectoryName, "bin", $env:MORYX_BUILD_CONFIG, "$projectName.dll");
-
- # If assembly does not exists, the project will be build
- if (-not (Test-Path $testAssembly)) {
- Invoke-Build $testProject
- }
-
- & $global:NUnitCli $testProject /config:"$env:MORYX_BUILD_CONFIG"
- }
-
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-SmokeTest([string]$RuntimePath, [int]$ModulesCount, [int]$InterruptTime) {
- $randomIncrement = Get-Random -Minimum 2000 -Maximum 2100
- Write-Step "Invoking Runtime SmokeTest Modules: $ModulesCount, Interrupt Time: $InterruptTime, Port Increment: $randomIncrement."
-
- & "$RuntimePath" @("smokeTest", "-e $ModulesCount", "-i $InterruptTime", "-p $randomIncrement")
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-CoverTests($SearchPath = $RootPath, $SearchFilter = "*.csproj", $FilterFile = "$RootPath\OpenCoverFilter.txt") {
- Write-Step "Starting cover tests from $SearchPath with filter $FilterFile."
-
- if (-not (Test-Path $SearchPath)) {
- Write-Host-Warning "$SearchPath does not exists, ignoring!";
- return;
- }
-
- $testProjects = Get-ChildItem $SearchPath -Recurse -Include $SearchFilter
- if ($testProjects.Length -eq 0) {
- Write-Host-Warning "No test projects found!"
- return;
- }
-
- if (-not (Test-Path $global:NUnitCli)) {
- Install-Tool "NUnit.Console" $NunitVersion $global:NunitCli;
- }
-
- if (-not (Test-Path $global:OpenCoverCli)) {
- Install-Tool "OpenCover" $OpenCoverVersion $global:OpenCoverCli;
- }
-
- if (-not (Test-Path $global:OpenCoverToCoberturaCli)) {
- Install-Tool "OpenCoverToCoberturaConverter" $OpenCoverToCoberturaVersion $global:OpenCoverToCoberturaCli;
- }
-
- CreateFolderIfNotExists $OpenCoverReportsDir;
- CreateFolderIfNotExists $NunitReportsDir;
-
- $includeFilter = "+[Moryx*]*";
- $excludeFilter = "-[*nunit*]* -[*Tests]* -[*Model*]*";
-
- if (Test-Path $FilterFile) {
- $ignoreContent = Get-Content $FilterFile;
-
- foreach ($line in $ignoreContent) {
- $parts = $line.Split(":");
- if ($parts.Count -lt 2) {
- continue
- }
-
- $filterType = $parts[0];
- $filterValue = $parts[1];
-
- if ($filterType.StartsWith("INCLUDE")) {
- $includeFilter += " $filterValue";
- }
-
- if ($filterType.StartsWith("EXCLUDE")) {
- $excludeFilter += " $filterValue";
- }
- }
-
- Write-Host "Active Filter: `r`n Include: $includeFilter `r`n Exclude: $excludeFilter";
- }
-
- ForEach($testProject in $testProjects ) {
- $projectName = ([System.IO.Path]::GetFileNameWithoutExtension($testProject.Name));
- $testAssembly = [System.IO.Path]::Combine($testProject.DirectoryName, "bin", $env:MORYX_BUILD_CONFIG, "$projectName.dll");
- $isNetCore = Get-CsprojIsNetCore($testProject);
-
- Write-Host "OpenCover Test: ${projectName}:";
-
- $nunitXml = ($NunitReportsDir + "\$projectName.TestResult.xml");
- $openCoverXml = ($OpenCoverReportsDir + "\$projectName.OpenCover.xml");
- $coberturaXml = ($CoberturaReportsDir + "\$projectName.Cobertura.xml");
-
- if ($isNetCore) {
- $targetArgs = '"test -v ' + $env:MORYX_TEST_VERBOSITY + ' -c ' + $env:MORYX_BUILD_CONFIG + ' ' + $testProject + '"';
- $openCoverAgs = "-target:$global:DotNetCli", "-targetargs:$targetArgs"
- }
- else {
- # If assembly does not exists, the project will be build
- if (-not (Test-Path $testAssembly)) {
- Invoke-Build $testProject
- }
-
- $openCoverAgs = "-target:$global:NunitCli", "-targetargs:/config:$env:MORYX_BUILD_CONFIG /result:$nunitXml $testAssembly"
- }
-
- $openCoverAgs += "-log:Debug", "-register:administrator", "-output:$openCoverXml", "-hideskipped:all", "-skipautoprops";
- $openCoverAgs += "-returntargetcode" # We need the nunit return code
- $openCoverAgs += "-filter:$includeFilter $excludeFilter"
-
- & $global:OpenCoverCli $openCoverAgs
-
- $exitCode = [int]::Parse($LastExitCode);
- if ($exitCode -ne 0) {
- $errorText = "";
- switch ($exitCode) {
- -1 { $errorText = "INVALID_ARG"; }
- -2 { $errorText = "INVALID_ASSEMBLY"; }
- -4 { $errorText = "INVALID_TEST_FIXTURE"; }
- -5 { $errorText = "UNLOAD_ERROR"; }
- Default { $errorText = "UNEXPECTED_ERROR"; }
- }
-
- if ($exitCode -gt 0) {
- $errorText = "FAILED_TESTS ($exitCode)";
- }
-
- Write-Host-Error "Nunit exited with $errorText for $projectName";
- Invoke-ExitCodeCheck $exitCode;
- }
-
- & $global:OpenCoverToCoberturaCli -input:$openCoverXml -output:$coberturaXml -sources:$rootPath
- Invoke-ExitCodeCheck $LastExitCode;
- }
-}
-
-function Get-CsprojIsNetCore($CsprojItem) {
- [xml]$csprojContent = Get-Content $CsprojItem.FullName
- $sdkProject = $csprojContent.Project.Sdk;
- if ($null -ne $sdkProject) {
- # Read Target Framework
- $targetFramework = $csprojContent.Project.PropertyGroup.TargetFramework;
- if ($targetFramework -Match "netcoreapp" -or $targetFramework -Match "net5.") {
- # NETCore
- return $true;
- }
- }
- return $false;
-}
-
-function Get-CsprojIsSdkProject($CsprojItem) {
- [xml]$csprojContent = Get-Content $CsprojItem.FullName
- $sdkProject = $csprojContent.Project.Sdk;
- if ($null -ne $sdkProject) {
- return $true;
- }
- return $false;
-}
-
-function Invoke-CoverReport {
- Write-Step "Creating cover report. Searching for OpenCover.xml files in $OpenCoverReportsDir."
-
- if (-not (Test-Path $OpenCoverReportsDir)) {
- Write-Host-Error "$OpenCoverReportsDir was not found!";
- Invoke-ExitCodeCheck 1;
- }
-
- if (-not (Test-Path $global:ReportGeneratorCli)) {
- Install-Tool "ReportGenerator" $ReportGeneratorVersion $global:ReportGeneratorCli;
- }
-
- $reports = (Get-ChildItem $OpenCoverReportsDir -Recurse -Include '*.OpenCover.xml');
- $asArgument = [string]::Join(";",$reports);
-
- CreateFolderIfNotExists $DocumentationArtifcacts;
-
- & $global:ReportGeneratorCli -reports:"$asArgument" -targetDir:"$DocumentationArtifcacts/OpenCover"
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-DocFx($Metadata = [System.IO.Path]::Combine($DocumentationDir, "docfx.json")) {
- Write-Step "Generating documentation using DocFx"
-
- if (-not (Test-Path $Metadata)) {
- Write-Host-Error "Metadata was not found at: $Metadata!"
- Invoke-ExitCodeCheck 1;
- }
-
- if (-not (Test-Path $global:DocFxCli)) {
- Install-Tool "docfx.console" $DocFxVersion $global:DocFxCli;
- }
-
- $docFxObj = (Get-Content $Metadata) | ConvertFrom-Json;
- $metadataFolder = [System.IO.Path]::GetDirectoryName($Metadata);
- $docFxDest = [System.IO.Path]::Combine($metadataFolder, $docFxObj.build.dest);
-
- & $global:DocFxCli $Metadata;
- Invoke-ExitCodeCheck $LastExitCode;
-
- CreateFolderIfNotExists $DocumentationArtifcacts;
- CopyAndReplaceFolder $docFxDest "$DocumentationArtifcacts\DocFx";
-}
-
-function Invoke-PackSdkProject($CsprojItem, [bool]$IncludeSymbols = $False) {
- Write-Host "Try to pack .NET SDK project: $($CsprojItem.Name) ...";
-
- # Check if the project should be packed
- $csprojFullName = $CsprojItem.FullName;
- [xml]$csprojContent = Get-Content $csprojFullName
- $createPackage = $csprojContent.Project.PropertyGroup.CreatePackage;
-;
- if ($null -eq $createPackage -or "false" -eq $createPackage) {
- Write-Host-Warning "... csproj not flagged with true: $($CsprojItem.Name)";
- return;
- }
-
- $packargs = "--output", "$NugetPackageArtifacts";
- $packargs += "--configuration", "$env:MORYX_BUILD_CONFIG";
- $packargs += "--verbosity", "$env:MORYX_NUGET_VERBOSITY";
- $packargs += "--no-build";
-
- if ($IncludeSymbols) {
- $packargs += "--include-symbols";
- $packargs += "--include-source";
- }
-
- & $global:DotNetCli pack "$csprojFullName" @packargs
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-PackFrameworkProject($CsprojItem, [bool]$IsTool = $False, [bool]$IncludeSymbols = $False) {
- Write-Host "Try to pack .NET Framework project: $CsprojItem.Name ...";
-
- # Check if there is a matching nuspec for the proj
- $csprojFullName = $CsprojItem.FullName;
- $nuspecPath = [IO.Path]::ChangeExtension($csprojFullName, "nuspec")
- if(-not (Test-Path $nuspecPath)) {
- Write-Host-Warning "Nuspec for project not found: $CsprojItem.Name";
- return;
- }
-
- $packargs = "-outputdirectory", "$NugetPackageArtifacts";
- $packargs += "-includereferencedprojects";
- $packargs += "-Version", "$env:MORYX_PACKAGE_VERSION";
- $packargs += "-Prop", "Configuration=$env:MORYX_BUILD_CONFIG";
- $packargs += "-Verbosity", "$env:MORYX_NUGET_VERBOSITY";
-
- if ($IncludeSymbols) {
- $packargs += "-Symbols";
- }
-
- if ($IsTool) {
- $packargs += "-Tool";
- }
-
- # Call nuget with default arguments plus optional
- & $global:NugetCli pack "$csprojFullName" @packargs
- Invoke-ExitCodeCheck $LastExitCode;
-}
-
-function Invoke-Pack($ProjectItem, [bool]$IsTool = $False, [bool]$IncludeSymbols = $False) {
- CreateFolderIfNotExists $NugetPackageArtifacts;
-
- if (Get-CsprojIsSdkProject($ProjectItem)) {
- Invoke-PackSdkProject $ProjectItem $IncludeSymbols;
- }
- else {
- Invoke-PackFrameworkProject $ProjectItem $IsTool $IncludeSymbols;
- }
-}
-
-function Invoke-PackAll([switch]$Symbols = $False) {
- Write-Host "Looking for .csproj files..."
- # Look for csproj in this directory
- foreach ($csprojItem in Get-ChildItem $RootPath -Recurse -Filter *.csproj) {
- Invoke-Pack -ProjectItem $csprojItem -IncludeSymbols $Symbols
- }
-}
-
-function Invoke-Publish {
- Write-Host "Pushing packages from $NugetPackageArtifacts to $env:MORYX_PACKAGE_TARGET"
-
- $packages = Get-ChildItem $NugetPackageArtifacts -Recurse -Include *.nupkg
- if ($packages.Length -gt 0 -and [string]::IsNullOrEmpty($env:MORYX_PACKAGE_TARGET)) {
- Write-Host-Error "There is no package target given. Set the environment varialble MORYX_PACKAGE_TARGET to publish packages.";
- Invoke-ExitCodeCheck 1;
- }
-
- foreach ($package in $packages) {
- Write-Host "Pushing package $package"
- & $global:DotNetCli nuget push $package --api-key $env:MORYX_NUGET_APIKEY --no-symbols --skip-duplicate --source $env:MORYX_PACKAGE_TARGET
- Invoke-ExitCodeCheck $LastExitCode;
- }
-
- $symbolPackages = Get-ChildItem $NugetPackageArtifacts -Recurse -Include *.snupkg
- if ($symbolPackages.Length -gt 0 -and [string]::IsNullOrEmpty($env:MORYX_PACKAGE_TARGET_V3)) {
- Write-Host-Error "There is no package (v3) target given. Set the environment varialble MORYX_PACKAGE_TARGET_V3 to publish snupkg symbol packages.";
- Invoke-ExitCodeCheck 1;
- }
-
- foreach ($symbolPackage in $symbolPackages) {
- Write-Host "Pushing symbol (snupkg) $symbolPackage"
- & $global:DotNetCli nuget push $symbolPackage --api-key $env:MORYX_NUGET_APIKEY --skip-duplicate --source $env:MORYX_PACKAGE_TARGET_V3
- Invoke-ExitCodeCheck $LastExitCode;
- }
-}
-
-function Set-Version ([string]$MajorMinorPatch) {
- $semVer2Regex = "^(?0|[1-9]\d*)\.(?0|[1-9]\d*)\.(?0|[1-9]\d*)(?:-(?(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$";
-
- $version = Read-VersionFromRef($MajorMinorPatch);
- Write-Host "Setting environment version to $version";
-
- # Match semVer2 regex
- $regexMatch = [regex]::Match($version, $semVer2Regex);
-
- if (-not $regexMatch.Success) {
- Write-Host "Could not parse version: $version";
- Invoke-ExitCodeCheck 1;
- }
-
- # Extract groups
- $matchgroups = $regexMatch.captures.groups;
- $majorGroup = $matchgroups[1];
- $minorGroup = $matchgroups[2];
- $patchGroup = $matchgroups[3];
- $preReleaseGroup = $matchgroups[4];
-
- # Compose Major.Minor.Patch
- $mmp = $majorGroup.Value + "." + $minorGroup.Value + "." + $patchGroup.Value;
-
- # Check if it is a pre release
- $env:MORYX_ASSEMBLY_VERSION = $majorGroup.Value + ".0.0.0" # 3.0.0.0
- $env:MORYX_FILE_VERSION = $mmp + "." + $env:MORYX_BUILDNUMBER; # 3.1.2.42
-
- if ($preReleaseGroup.Success) {
- $env:MORYX_INFORMATIONAL_VERSION = $mmp + "-" + $preReleaseGroup.Value + "+" + $global:GitCommitHash; # 3.1.2-beta.1+d95a996ed5ba14a1421dafeb844a56ab08211ead
- $env:MORYX_PACKAGE_VERSION = $mmp + "-" + $preReleaseGroup.Value;
- } else {
- $env:MORYX_INFORMATIONAL_VERSION = $mmp + "+" + $global:GitCommitHash; # 3.1.2+d95a996ed5ba14a1421dafeb844a56ab08211ead
- $env:MORYX_PACKAGE_VERSION = $mmp;
- }
-}
-
-function Read-VersionFromRef([string]$MajorMinorPatch) {
- function preReleaseVersion ([string] $name)
- {
- $name = $name.Replace("/","").ToLower();
- return "$MajorMinorPatch-$name.$env:MORYX_BUILDNUMBER";;
- }
-
- $ref = "";
- if ($env:GITHUB_WORKFLOW) { # GitHub Workflow
- Write-Host "Reading version from 'GitHub Workflow'";
- $ref = $env:GITHUB_REF;
-
- if ($ref.StartsWith("refs/tags/")) {
- if ($ref.StartsWith("refs/tags/v")) {
- # Its a version tag
- $version = $ref.Replace("refs/tags/v","")
- }
- else {
- # Just a tag
- $name = $ref.Replace("refs/tags/","");
- $version = = preReleaseVersion($name);
- }
- }
- elseif ($ref.StartsWith("refs/heads/")) {
- # Its a branch
- $name = $ref.Replace("refs/heads/","");
- $version = preReleaseVersion($name);
- }
- else {
- $version = preReleaseVersion($ref);
- }
- }
- else { # Local build
- Write-Host "Reading version from 'local'";
- $ref = (& $global:GitCli rev-parse --abbrev-ref HEAD);
- $version = preReleaseVersion($ref);
- }
-
- return $version;
-}
-
-function Set-AssemblyVersion([string]$InputFile) {
- $file = Get-Childitem -Path $inputFile;
-
- if (-Not $file) {
- Write-Host "AssemblyInfo: $inputFile was not found!";
- exit 1;
- }
-
- Write-Host "Applying assembly info of $($file.FullName) -> $env:MORYX_ASSEMBLY_VERSION ";
-
- $assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+)){3}"\)';
- $assemblyVersion = 'AssemblyVersion("' + $env:MORYX_ASSEMBLY_VERSION + '")';
-
- $assemblyFileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+)){3}"\)';
- $assemblyFileVersion = 'AssemblyFileVersion("' + $env:MORYX_FILE_VERSION + '")';
-
- $assemblyInformationalVersionPattern = 'AssemblyInformationalVersion\("[0-9]+(\.([0-9]+)){3}"\)';
- $assemblyInformationalVersion = 'AssemblyInformationalVersion("' + $env:MORYX_INFORMATIONAL_VERSION + '")';
-
- $assemblyConfigurationPattern = 'AssemblyConfiguration\("\w+"\)';
- $assemblyConfiguration = 'AssemblyConfiguration("' + $env:MORYX_BUILD_CONFIG + '")';
-
- $content = (Get-Content $file.FullName) | ForEach-Object {
- ForEach-Object {$_ -replace $assemblyVersionPattern, $assemblyVersion } |
- ForEach-Object {$_ -replace $assemblyFileVersionPattern, $assemblyFileVersion } |
- ForEach-Object {$_ -replace $assemblyInformationalVersionPattern, $assemblyInformationalVersion } |
- ForEach-Object {$_ -replace $assemblyConfigurationPattern, $assemblyConfiguration }
- }
-
- Out-File -InputObject $content -FilePath $file.FullName -Encoding utf8;
-}
-
-function Set-AssemblyVersions([string[]]$Ignored = $(), [string]$SearchPath = $RootPath) {
- $Ignored = $Ignored + "\\.build\\" + "\\Tests\\" + "\\IntegrationTests\\" + "\\SystemTests\\";
-
- $assemblyInfos = Get-ChildItem -Path $RootPath -include "*AssemblyInfo.cs" -Recurse | Where-Object {
- $fullName = $_.FullName;
- return -not ($Ignored.Where({ $fullName -match $_ }).Count -gt 0);
- }
-
- if ($assemblyInfos)
- {
- Write-Host "Will apply version to $($assemblyInfos.Count) AssemblyInfos.";
- foreach ($file in $assemblyInfos) {
- Set-AssemblyVersion -InputFile $file;
- }
- }
-}
-
-function CreateFolderIfNotExists([string]$Folder) {
- if (-not (Test-Path $Folder)) {
- Write-Host "Creating missing directory '$Folder'"
- New-Item $Folder -Type Directory | Out-Null
- }
-}
-
-function CopyAndReplaceFolder($SourceDir, $TargetDir) {
- Write-Host-Info "Copy $SourceDir to $TargetDir!"
- # Remove old folder if exists
- if (Test-Path $TargetDir) {
- Write-Host "Target path already exists, removing ..." -ForegroundColor Yellow
- Remove-Item -Recurse -Force $TargetDir
- }
-
- # Copy to target path
- Write-Host "Copy from $SourceDir to $TargetDir ..." -ForegroundColor Green
- Copy-Item -Path $SourceDir -Recurse -Destination $TargetDir -Container
-}
diff --git a/.build/Output.ps1 b/.build/Output.ps1
deleted file mode 100644
index 913f5577b..000000000
--- a/.build/Output.ps1
+++ /dev/null
@@ -1,36 +0,0 @@
-################################
-# Functions for Console Output #
-################################
-
-function Write-Step([string]$step) {
- Write-Host "########################################################################################################" -foreground Magenta;
- Write-Host "#### $step" -foreground Magenta;
- Write-Host "########################################################################################################" -foreground Magenta
-}
-
-function Write-Variable ([string]$variableName, [string]$variableValue) {
- Write-Host ($variableName + " = " + $variableValue)
-}
-
-function Invoke-ExitCodeCheck([string]$exitCode) {
- if ([int]::Parse($exitCode) -gt 0) {
- Write-Host "This is the end, you know (ExitCode: $exitCode) - Lady, the plans we had went all wrong - We ain't nothing but fight and shout and tears." -ForegroundColor Red
- exit $exitCode;
- }
-}
-
-function Write-Host-Info([string]$message) {
- Write-Host $message
-}
-
-function Write-Host-Success([string]$message) {
- Write-Host $message -ForegroundColor Green
-}
-
-function Write-Host-Warning([string]$message) {
- Write-Host $message -ForegroundColor Yellow
-}
-
-function Write-Host-Error([string]$message) {
- Write-Host $message -ForegroundColor Red
-}
\ No newline at end of file
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index a6f81c1c2..fde8ac4b0 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -12,94 +12,87 @@ on:
branches:
- dev
- future
-
+
env:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
+ dotnet_sdk_version: '8.0.100'
REPOSITORY_NAME: ${{ github.event.repository.name }}
+ MORYX_PACKAGE_TARGET_DEV: 'https://www.myget.org/F/moryx-oss-ci/api/v2/package'
+ MORYX_PACKAGE_TARGET_V3_DEV: 'https://www.myget.org/F/moryx-oss-ci/api/v3/index.json'
+ MORYX_PACKAGE_TARGET_FUTURE: 'https://www.myget.org/F/moryx-oss-ci/api/v2/package'
+ MORYX_PACKAGE_TARGET_V3_FUTURE: 'https://www.myget.org/F/moryx-oss-ci/api/v3/index.json'
+ MORYX_PACKAGE_TARGET_RELEASE: 'https://api.nuget.org/v3/index.json'
+ MORYX_PACKAGE_TARGET_V3_RELEASE: 'https://api.nuget.org/v3/index.json'
jobs:
+ EnvVar:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo ""
+ outputs:
+ dotnet_sdk_version: ${{ env.dotnet_sdk_version }}
+ REPOSITORY_NAME: ${{ env.REPOSITORY_NAME }}
+ MORYX_PACKAGE_TARGET_DEV: ${{ env.MORYX_PACKAGE_TARGET_DEV }}
+ MORYX_PACKAGE_TARGET_V3_DEV: ${{ env.MORYX_PACKAGE_TARGET_V3_DEV }}
+ MORYX_PACKAGE_TARGET_FUTURE: ${{ env.MORYX_PACKAGE_TARGET_FUTURE }}
+ MORYX_PACKAGE_TARGET_V3_FUTURE: ${{ env.MORYX_PACKAGE_TARGET_V3_FUTURE }}
+ MORYX_PACKAGE_TARGET_RELEASE: ${{ env.MORYX_PACKAGE_TARGET_RELEASE }}
+ MORYX_PACKAGE_TARGET_V3_RELEASE: ${{ env.MORYX_PACKAGE_TARGET_V3_RELEASE }}
+
Build:
- uses: PHOENIXCONTACT/tools/.github/workflows/build-tool.yml@release-6
+ needs: [EnvVar]
+ uses: phoenixcontact/tools/.github/workflows/build-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ dotnet_sdk_version: ${{ needs.EnvVar.outputs.dotnet_sdk_version }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
UnitTests:
- needs: [Build]
- uses: PHOENIXCONTACT/tools/.github/workflows/unittest-tool.yml@release-6
+ needs: [EnvVar, Build]
+ uses: phoenixcontact/tools/.github/workflows/unittest-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ dotnet_sdk_version: ${{ needs.EnvVar.outputs.dotnet_sdk_version }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
IntegrationTests:
- needs: [Build]
- uses: PHOENIXCONTACT/tools/.github/workflows/integrationtest-tool.yml@release-6
+ needs: [EnvVar, Build]
+ uses: phoenixcontact/tools/.github/workflows/integrationtest-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ dotnet_sdk_version: ${{ needs.EnvVar.outputs.dotnet_sdk_version }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
ReportGenerator:
- needs: [UnitTests, IntegrationTests]
- uses: PHOENIXCONTACT/tools/.github/workflows/reportgenerator-tool.yml@release-6
+ needs: [EnvVar, UnitTests, IntegrationTests]
+ uses: phoenixcontact/tools/.github/workflows/reportgenerator-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
Publish-Test-Coverage:
- needs: [ReportGenerator]
- uses: PHOENIXCONTACT/tools/.github/workflows/publish-test-coverage-tool.yml@release-6
+ needs: [EnvVar, ReportGenerator]
+ uses: phoenixcontact/tools/.github/workflows/publish-test-coverage-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- Documentation:
- needs: [UnitTests]
- uses: PHOENIXCONTACT/tools/.github/workflows/documentation-tool.yml@release-6
- with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ # currently not working
+ # Documentation:
+ # needs: [EnvVar, UnitTests]
+ # uses: phoenixcontact/tools/.github/workflows/documentation-tool.yml@main
+ # with:
+ # REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
Publish:
- needs: [UnitTests]
- uses: PHOENIXCONTACT/tools/.github/workflows/publish-tool.yml@release-6
+ needs: [EnvVar, UnitTests]
+ uses: phoenixcontact/tools/.github/workflows/publish-tool.yml@main
with:
- MORYX_OPTIMIZE_CODE: "false"
- MORYX_BUILD_CONFIG: "Release"
- MORYX_BUILDNUMBER: ${{github.run_number}}
- dotnet_sdk_version: '7.x'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- REPOSITORY_NAME: ${{ github.event.repository.name }}
+ dotnet_sdk_version: ${{ needs.EnvVar.outputs.dotnet_sdk_version }}
+ REPOSITORY_NAME: ${{ needs.EnvVar.outputs.REPOSITORY_NAME }}
+ MORYX_PACKAGE_TARGET_DEV: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_DEV }}
+ MORYX_PACKAGE_TARGET_V3_DEV: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_V3_DEV }}
+ MORYX_PACKAGE_TARGET_FUTURE: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_FUTURE }}
+ MORYX_PACKAGE_TARGET_V3_FUTURE: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_V3_FUTURE }}
+ MORYX_PACKAGE_TARGET_RELEASE: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_RELEASE }}
+ MORYX_PACKAGE_TARGET_V3_RELEASE: ${{ needs.EnvVar.outputs.MORYX_PACKAGE_TARGET_V3_RELEASE }}
secrets:
MYGET_TOKEN: ${{secrets.MYGET_TOKEN}}
NUGET_TOKEN: ${{secrets.NUGET_TOKEN}}
diff --git a/Build.ps1 b/Build.ps1
deleted file mode 100644
index 4b65211d1..000000000
--- a/Build.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-param (
- [switch]$SetAssemblyVersion,
- [switch]$Build,
-
- [switch]$SmokeTests,
- [switch]$UnitTests,
- [switch]$IntegrationTests,
- [switch]$SystemTests,
-
- [switch]$CoverReport,
- [switch]$GenerateDocs,
-
- [switch]$Pack,
- [switch]$Publish
-)
-
-# Load Toolkit
-. ".build\BuildToolkit.ps1"
-
-# Set MSBuild to latest version
-$MsBuildVersion = "latest";
-
-# Initialize Toolkit
-Invoke-Initialize -Version (Get-Content "VERSION");
-
-if ($Build) {
- Invoke-Build ".\MORYX-Framework.sln"
-}
-
-if ($SmokeTests) {
- $runtimePath = "$RootPath\src\StartProject\bin\$env:MORYX_BUILD_CONFIG\StartProject.exe";
- Invoke-SmokeTest $runtimePath 3 6000
-}
-
-if ($UnitTests) {
- Invoke-CoverTests -SearchFilter "*.Tests.csproj"
-}
-
-if ($IntegrationTests) {
- Invoke-CoverTests -SearchFilter "*.IntegrationTests.csproj"
-}
-
-if ($SystemTests) {
- Invoke-CoverTests -SearchFilter "*.SystemTests.csproj"
-}
-
-if ($CoverReport) {
- Invoke-CoverReport
-}
-
-if ($GenerateDocs) {
- Invoke-DocFx
-}
-
-if ($Pack) {
- Invoke-PackAll -Symbols
-}
-
-if ($Publish) {
- Invoke-Publish
-}
-
-Write-Host "Success!"
\ No newline at end of file
diff --git a/Directory.build.props b/Directory.Build.props
similarity index 91%
rename from Directory.build.props
rename to Directory.Build.props
index c735b57d6..a5baa5c61 100644
--- a/Directory.build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- 10.0
+ latest
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 1d84decb3..d12d3f6bd 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,27 +1,28 @@
-
+
- 6.0.0
- 6.0.0
+ 8.0.0
+ 8.0.0
+ latest
-
-
-
+
+
+
-
-
-
+
+
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -43,12 +44,10 @@
-
+
-
-
-
+
diff --git a/LICENSE b/LICENSE
index f433b1a53..33f844f2c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
Apache License
Version 2.0, January 2004
- http://www.apache.org/licenses/
+ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
diff --git a/VERSION b/VERSION
index dc0208aba..fbb9ea12d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.3.1
+8.2.0
diff --git a/docs/migrations/v6_to_v8.md b/docs/migrations/v6_to_v8.md
new file mode 100644
index 000000000..7212ddae1
--- /dev/null
+++ b/docs/migrations/v6_to_v8.md
@@ -0,0 +1,29 @@
+# Migration from MORYX Framework v6 to v8
+
+
+## Local Container Refactoring
+The DI container within modules based on Castle Windsor was refactored and simplified. The most changes are caused by removing the historic split between local and global container, which was obsolete after switching the global container to ServiceCollection. We also removed the concept of installers and registrators and replaced everything with API on `IContainer` and extensions inspired by the `IServiceCollection`.
+
+- **Attribute changes:** The base attributes for registration were removed, use `ComponentAttribute`, `PluginAttribute` and `PluginFactory` instead.
+- **Installers removed** The concept of installes was removed and with it their implementations `AutoInstaller` and `DependencyInstaller`. They were replaced by the extensions `LoadFromAssembly` with different signature options for `DependencyRegistrationAttribute` and `Predicate`
+- **LoadComponents** was removed as a dedicate feature and is now an extension on `IContainer`. It has also been restricted to public/exported types.
+- **IContainerHost** was removed. The seperate interface for accessing a modules container just caused unnecessary casts and the risk of invalid type. The property `Container` was added to `IServerModule` instead.
+- **Extend** The flexible method for passing facilities to Castle was removed as it was only added and used by WCF.
+- **MoryxFacility** All MORYX specific behavior like strategies and `Named` import overrides were refactored to follow Castle best practises and are now isolated in the `MoryxFacility`. This enables everyone to achieve the MORYX DI behavior with a Castle Container without the MORYX wrapper.
+- **Installers** As previously mentioned installers were removed, but since the API on `IContainer` now supports everything previously reserved for installers and registrators, just migrate the registration onto the container like the [DbContextContainerExtension](https://github.com/PHOENIXCONTACT/MORYX-Framework/blob/future/src/Moryx.Model/DbContextContainerExtension.cs) or the [BasicInterceptorInstaller](https://github.com/PHOENIXCONTACT/MORYX-Framework/blob/future/src/Moryx.TestTools.UnitTest/BasicInterceptorInstaller.cs)
+
+## ServerModuleBase
+
+To simplify development and prepare easier integration of the Moryx.Cli we merged the `ServerModuleFacadeControllerBase` into the `ServerModuleBase`. Just replace the base type if your module is affected by this.
+
+## GetObjectData(SerializationInfo info, StreamingContext context)
+
+Removed all overrides of the obsolete method `Exception.GetObjectData(SerializationInfo info, StreamingContext context)` as well as all constructors which were calling the base class constructor `Exception(SerializationInfo info, StreamingContext context)`
+The following classes are affected by this change
+- MissingFacadeException
+- HealthStateException
+- InvalidConfigException
+
+## Merged IPublicResource into IResource
+
+`IPublicResource` and `IResource` were merged into `IResource`, since the differentiaten between those was hard to understand for some and barely had any real world advantages. Now literally "Everything is a resource".
\ No newline at end of file
diff --git a/docs/tutorials/HowToCreateAProduct.md b/docs/tutorials/HowToCreateAProduct.md
index c62cb9f8e..2a00fdc6f 100644
--- a/docs/tutorials/HowToCreateAProduct.md
+++ b/docs/tutorials/HowToCreateAProduct.md
@@ -1,11 +1,11 @@
---
uid: HowToCreateAProduct
---
-# How to create a resource
+# How to create a product
This tutorial shows how [Products](../../src/Moryx.AbstractionLayer/Products/ProductType.cs) should be implemented. Look [here](../articles/Products/Concept.md) if you are not firm with the concept of a `Product`.
-For products we differentiate between [ProductType](../../src/Moryx.AbstractionLayer/Products/ProductType.cs) and [ProductInstance](../../src/Moryx.AbstractionLayer/Products/ProductInstance.cs). The `ProductType` is what you can order in a catalog, while the `ProductInstance` is what you received after ordering: an instance of the product with its unique serialnumber. So that a `ProductType` can be producted it needs a corresponding `ProductInstance`. If your application isn't used for production, you can skip the `ProductInstances`.
+For products we differentiate between [ProductType](../../src/Moryx.AbstractionLayer/Products/ProductType.cs) and [ProductInstance](../../src/Moryx.AbstractionLayer/Products/ProductInstance.cs). The `ProductType` is what you can order in a catalog, while the `ProductInstance` is what you received after ordering: an instance of the product with its unique serialnumber. So that a `ProductType` can be produced it needs a corresponding `ProductInstance`. If your application isn't used for production, you can skip the `ProductInstances`.
## Create a basic ProductType and ProductInstance
All ProductTypes are derived from `ProductType`. The methode `Instantiate()` returns an object of the correspoding `ProductInstance`.
diff --git a/docs/tutorials/HowToTestAModule.md b/docs/tutorials/HowToTestAModule.md
index 2796eecf6..0ee512088 100644
--- a/docs/tutorials/HowToTestAModule.md
+++ b/docs/tutorials/HowToTestAModule.md
@@ -3,7 +3,7 @@
In order to test a module in its lifecycle with its respective facade we offer the `Moryx.TestTools.IntegrationTest`.
The package brings a `MoryxTestEnvironment`.
With this class you can first create mocks for all module facades your module dependents on using the static `CreateModuleMock` method.
-Afterwards you can create the environment using an implementation of the `ServerModuleFacadeControllerBase`, an instance of the `ConfigBase` and the set of dependency mocks.
+Afterwards you can create the environment using an implementation of the `ServerModuleBase` class, an instance of the `ConfigBase` and the set of dependency mocks.
The first two parameters are usually your `ModuleController` and your `ModuleConfig`.
The following example shows a setup for the `IShiftManagement` facade interface. The module depends on the `IResourceManagement` and `IOperatorManagement` facades.
diff --git a/src/Moryx.AbstractionLayer.Products.Endpoints/Moryx.AbstractionLayer.Products.Endpoints.csproj b/src/Moryx.AbstractionLayer.Products.Endpoints/Moryx.AbstractionLayer.Products.Endpoints.csproj
index 82b4823b5..6c7673222 100644
--- a/src/Moryx.AbstractionLayer.Products.Endpoints/Moryx.AbstractionLayer.Products.Endpoints.csproj
+++ b/src/Moryx.AbstractionLayer.Products.Endpoints/Moryx.AbstractionLayer.Products.Endpoints.csproj
@@ -1,10 +1,9 @@
- net6.0
+ net8.0
Endpoints for the Product Facade
true
- true
MORYX;IIoT;IoT;
diff --git a/src/Moryx.AbstractionLayer.Products.Endpoints/ProductManagementController.cs b/src/Moryx.AbstractionLayer.Products.Endpoints/ProductManagementController.cs
index 71654e272..516876d7e 100644
--- a/src/Moryx.AbstractionLayer.Products.Endpoints/ProductManagementController.cs
+++ b/src/Moryx.AbstractionLayer.Products.Endpoints/ProductManagementController.cs
@@ -18,7 +18,6 @@
using Moryx.AbstractionLayer.Resources;
using Moryx.Runtime.Modules;
using System.ComponentModel;
-using Moryx.Runtime.Container;
namespace Moryx.AbstractionLayer.Products.Endpoints
{
@@ -38,9 +37,8 @@ public ProductManagementController(IProductManagement productManagement,
{
_productManagement = productManagement;
- var module = moduleManager.AllModules.FirstOrDefault(module => module is IFacadeContainer);
- var host = (IContainerHost)module;
- _productConverter = new ProductConverter(_productManagement, host.Container, serviceProvider);
+ var module = moduleManager.AllModules.FirstOrDefault(module => module is IFacadeContainer);
+ _productConverter = new ProductConverter(_productManagement, module.Container, serviceProvider);
}
#region importers
@@ -188,7 +186,7 @@ public ActionResult GetTypeById(long id)
{
productType = _productManagement.LoadType(id);
}
- catch (ProductNotFoundException e)
+ catch (ProductNotFoundException)
{
}
if (productType == null)
diff --git a/src/Moryx.AbstractionLayer.Products.Endpoints/ProductPermissions.cs b/src/Moryx.AbstractionLayer.Products.Endpoints/ProductPermissions.cs
index d9399c4d9..df0e1b110 100644
--- a/src/Moryx.AbstractionLayer.Products.Endpoints/ProductPermissions.cs
+++ b/src/Moryx.AbstractionLayer.Products.Endpoints/ProductPermissions.cs
@@ -1,15 +1,53 @@
namespace Moryx.AbstractionLayer.Products.Endpoints
{
+ ///
+ /// Permissions used to authorize for the
+ ///
public static class ProductPermissions
{
+ ///
+ /// Prefix used for all permissions of the controller
+ ///
private const string _prefix = "Moryx.Products.";
+
+ ///
+ /// Permission for all actions related to viewing one or multiple product types
+ ///
public const string CanViewTypes = _prefix + "CanViewTypes";
+
+ ///
+ /// Permission for all actions related to creating and editing recipes
+ ///
public const string CanCreateAndEditRecipes = _prefix + "CanCreateAndEditRecipes";
+
+ ///
+ /// Permission for all actions related to editing one or multiple product types
+ ///
public const string CanEditType = _prefix + "CanEditType";
+
+ ///
+ /// Permission for all actions related to duplicating one or multiple product types
+ ///
public const string CanDuplicateType = _prefix + "CanDuplicateType";
+
+ ///
+ /// Permission for all actions related to see and execute a product importer
+ ///
public const string CanImport = _prefix + "CanImport";
+
+ ///
+ /// Permission for all actions related to deleting one or multiple product types
+ ///
public const string CanDeleteType = _prefix + "CanDeleteType";
+
+ ///
+ /// Permission for all actions related to viewing one or multiple product instances
+ ///
public const string CanViewInstances = _prefix + "CanViewInstances";
+
+ ///
+ /// Permission for all actions related to creating one or multiple product instances
+ ///
public const string CanCreateInstances = _prefix + "CanCreateInstances";
}
}
diff --git a/src/Moryx.AbstractionLayer.Products.Endpoints/WorkplanPermissions.cs b/src/Moryx.AbstractionLayer.Products.Endpoints/WorkplanPermissions.cs
index d09a886fe..4ae545160 100644
--- a/src/Moryx.AbstractionLayer.Products.Endpoints/WorkplanPermissions.cs
+++ b/src/Moryx.AbstractionLayer.Products.Endpoints/WorkplanPermissions.cs
@@ -1,10 +1,28 @@
namespace Moryx.AbstractionLayer.Products.Endpoints
{
+ ///
+ /// Permissions used to authorize for the
+ ///
public static class WorkplanPermissions
{
+ ///
+ /// Prefix used for all permissions of the controller
+ ///
private const string _prefix = "Moryx.Workplans.";
+
+ ///
+ /// Permission for all actions related to viewing one or multiple workplans
+ ///
public const string CanView = _prefix + "CanView";
+
+ ///
+ /// Permission for all actions related to editing or creating one or multiple workplans
+ ///
public const string CanEdit = _prefix + "CanEdit";
+
+ ///
+ /// Permission for all actions related to deleting one or multiple workplans
+ ///
public const string CanDelete = _prefix + "CanDelete";
}
}
diff --git a/src/Moryx.AbstractionLayer.Resources.Endpoints/Moryx.AbstractionLayer.Resources.Endpoints.csproj b/src/Moryx.AbstractionLayer.Resources.Endpoints/Moryx.AbstractionLayer.Resources.Endpoints.csproj
index 8c981b0b2..21907fa30 100644
--- a/src/Moryx.AbstractionLayer.Resources.Endpoints/Moryx.AbstractionLayer.Resources.Endpoints.csproj
+++ b/src/Moryx.AbstractionLayer.Resources.Endpoints/Moryx.AbstractionLayer.Resources.Endpoints.csproj
@@ -1,10 +1,9 @@
-
+
- net6.0
+ net8.0
true
REST Api in order to interact with the resource management
- true
MORYX;IIoT;IoT;Resource
diff --git a/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourceManagementController.cs b/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourceManagementController.cs
index 29b106227..15aca8484 100644
--- a/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourceManagementController.cs
+++ b/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourceManagementController.cs
@@ -15,7 +15,6 @@
using Moryx.Tools;
using Moryx.AbstractionLayer.Properties;
using Moryx.Runtime.Modules;
-using Moryx.Runtime.Container;
using Moryx.Configuration;
namespace Moryx.AbstractionLayer.Resources.Endpoints
@@ -40,8 +39,7 @@ public ResourceModificationController(IResourceManagement resourceManagement,
_resourceManagement = resourceManagement ?? throw new ArgumentNullException(nameof(resourceManagement));
_resourceTypeTree = resourceTypeTree ?? throw new ArgumentNullException(nameof(resourceTypeTree));
var module = moduleManager.AllModules.FirstOrDefault(module => module is IFacadeContainer);
- var containerHost = (IContainerHost)module;
- _serialization = new ResourceSerialization(containerHost.Container, serviceProvider);
+ _serialization = new ResourceSerialization(module.Container, serviceProvider);
}
[HttpGet]
@@ -64,7 +62,7 @@ public ActionResult GetDetailsBatch([FromQuery] long[] ids)
var converter = new ResourceToModelConverter(_resourceTypeTree, _serialization);
if (ids is null || ids.Length == 0)
- ids = _resourceManagement.GetResources().Select(r => r.Id).ToArray();
+ ids = _resourceManagement.GetResources().Select(r => r.Id).ToArray();
return ids.Select(id => _resourceManagement.Read(id, r => converter.GetDetails(r)))
.Where(details => details != null).ToArray();
diff --git a/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourcePermissions.cs b/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourcePermissions.cs
index 926f7dc64..4abe04817 100644
--- a/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourcePermissions.cs
+++ b/src/Moryx.AbstractionLayer.Resources.Endpoints/ResourcePermissions.cs
@@ -1,14 +1,49 @@
namespace Moryx.AbstractionLayer.Resources.Endpoints
{
+ ///
+ /// Permissions used to authorize for the
+ ///
public static class ResourcePermissions
{
+ ///
+ /// Prefix used for all permissions of the controller
+ ///
private const string _prefix = "Moryx.Resources.";
+
+ ///
+ /// Permission for all actions related to viewing the resource instance tree
+ ///
public const string CanViewTree = _prefix + "CanViewTree";
+
+ ///
+ /// Permission for all actions related to viewing the instance information of a resource
+ ///
public const string CanViewDetails = _prefix + "CanViewDetails";
+
+ ///
+ /// Permission for all actions related to editing the resource graph and its members
+ ///
public const string CanEdit = _prefix + "CanEdit";
+
+ // ToDo: Rename permission to CanViewTypeTree
+ ///
+ /// Permission for all actions related to viewing the resource type tree
+ ///
public const string CanViewTypeTree = _prefix + "CanAddResource";
+
+ ///
+ /// Permission for all actions related to adding one or multiple resources
+ ///
public const string CanAdd = _prefix + "CanAdd";
+
+ ///
+ /// Permission for all actions related to adding one or multiple resources
+ ///
public const string CanDelete = _prefix + "CanDelete";
+
+ ///
+ /// Permission for all actions related to invoking a method on a resource
+ ///
public const string CanInvokeMethod = _prefix + "CanInvokeMethod";
}
}
diff --git a/src/Moryx.AbstractionLayer.TestTools/DummyProductPartLink.cs b/src/Moryx.AbstractionLayer.TestTools/DummyProductPartLink.cs
index 1c7cc4098..f700d5988 100644
--- a/src/Moryx.AbstractionLayer.TestTools/DummyProductPartLink.cs
+++ b/src/Moryx.AbstractionLayer.TestTools/DummyProductPartLink.cs
@@ -11,6 +11,7 @@ namespace Moryx.AbstractionLayer.TestTools
///
public class DummyProductPartLink : ProductPartLink
{
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyProductPartLink;
diff --git a/src/Moryx.AbstractionLayer.TestTools/DummyProductRecipe.cs b/src/Moryx.AbstractionLayer.TestTools/DummyProductRecipe.cs
index 41ce23945..0ee5ca41b 100644
--- a/src/Moryx.AbstractionLayer.TestTools/DummyProductRecipe.cs
+++ b/src/Moryx.AbstractionLayer.TestTools/DummyProductRecipe.cs
@@ -13,6 +13,7 @@ namespace Moryx.AbstractionLayer.TestTools
///
public class DummyProductRecipe : ProductRecipe
{
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyProductRecipe;
@@ -27,12 +28,18 @@ public override bool Equals(object obj)
}
}
+ ///
+ /// Dummy implementation of a workplan recipe.
+ ///
public class DummyProductWorkplanRecipe : DummyProductRecipe, IWorkplanRecipe
{
+ ///
public IWorkplan Workplan { get; set; }
+ ///
public ICollection DisabledSteps { get; set; }
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyProductWorkplanRecipe;
diff --git a/src/Moryx.AbstractionLayer.TestTools/DummyProductType.cs b/src/Moryx.AbstractionLayer.TestTools/DummyProductType.cs
index 8ffecfaf1..54e9e029e 100644
--- a/src/Moryx.AbstractionLayer.TestTools/DummyProductType.cs
+++ b/src/Moryx.AbstractionLayer.TestTools/DummyProductType.cs
@@ -17,6 +17,7 @@ protected override ProductInstance Instantiate()
{
return new DummyProductInstance();
}
+///
public override bool Equals(object obj)
{
@@ -51,6 +52,7 @@ protected override ProductInstance Instantiate()
///
public IEnumerable ProductPartLinkEnumerable { get; set; }
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyProductTypeWithParts;
@@ -86,7 +88,8 @@ protected override ProductInstance Instantiate()
/// Second dummy ProductFile
///
public ProductFile SecondProductFile { get; set; }
-
+
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyProductTypeWithFiles;
diff --git a/src/Moryx.AbstractionLayer.TestTools/DummyWorkplan.cs b/src/Moryx.AbstractionLayer.TestTools/DummyWorkplan.cs
index 0e131f0ab..db255b711 100644
--- a/src/Moryx.AbstractionLayer.TestTools/DummyWorkplan.cs
+++ b/src/Moryx.AbstractionLayer.TestTools/DummyWorkplan.cs
@@ -6,8 +6,12 @@
namespace Moryx.AbstractionLayer.TestTools
{
+ ///
+ /// Dummy implementation of with overridden method for testing purposes.
+ ///
public class DummyWorkplan : Workplan
{
+ ///
public override bool Equals(object obj)
{
var toCompareWith = obj as DummyWorkplan;
diff --git a/src/Moryx.AbstractionLayer.TestTools/Moryx.AbstractionLayer.TestTools.csproj b/src/Moryx.AbstractionLayer.TestTools/Moryx.AbstractionLayer.TestTools.csproj
index bde0a3899..d261b6e64 100644
--- a/src/Moryx.AbstractionLayer.TestTools/Moryx.AbstractionLayer.TestTools.csproj
+++ b/src/Moryx.AbstractionLayer.TestTools/Moryx.AbstractionLayer.TestTools.csproj
@@ -1,21 +1,15 @@
- net6.0
+ net8.0
true
Additional AbstractionLayer implementations for Tests
- true
MORYX;IIoT;IoT;Abstraction;Tests
-
-
-
-
-
diff --git a/src/Moryx.AbstractionLayer.TestTools/Resources/ResourceGraphMock.cs b/src/Moryx.AbstractionLayer.TestTools/Resources/ResourceGraphMock.cs
index 895b3f867..8eb4b45e5 100644
--- a/src/Moryx.AbstractionLayer.TestTools/Resources/ResourceGraphMock.cs
+++ b/src/Moryx.AbstractionLayer.TestTools/Resources/ResourceGraphMock.cs
@@ -16,38 +16,48 @@ public class ResourceGraphMock : IResourceGraph
{
private IDictionary _typeMap;
+ ///
+ /// The list of resources in this graph
+ ///
public List Graph { get; set; }
+ ///
public Resource Get(long id)
{
return Graph.FirstOrDefault(r => r.Id == id);
}
+ ///
public TResource GetResource() where TResource : class, IResource
{
throw new NotImplementedException();
}
+ ///
public TResource GetResource(long id) where TResource : class, IResource
{
throw new NotImplementedException();
}
+ ///
public TResource GetResource(string name) where TResource : class, IResource
{
throw new NotImplementedException();
}
+ ///
public TResource GetResource(Func predicate) where TResource : class, IResource
{
throw new NotImplementedException();
}
+ ///
public IEnumerable GetResources() where TResource : class, IResource
{
throw new NotImplementedException();
}
+ ///
public IEnumerable GetResources(Func predicate) where TResource : class, IResource
{
throw new NotImplementedException();
@@ -101,6 +111,7 @@ public bool Destroy(IResource resource, bool permanent)
return Destroy(resource);
}
+ ///
public void Save(IResource resource)
{
}
diff --git a/src/Moryx.AbstractionLayer/Moryx.AbstractionLayer.csproj b/src/Moryx.AbstractionLayer/Moryx.AbstractionLayer.csproj
index 6ce2a84f3..f3779fc05 100644
--- a/src/Moryx.AbstractionLayer/Moryx.AbstractionLayer.csproj
+++ b/src/Moryx.AbstractionLayer/Moryx.AbstractionLayer.csproj
@@ -1,10 +1,9 @@
- netstandard2.0;net6.0
+ netstandard2.0;net8.0
true
Domain model types and definitions of Cyber-physical systems in IIoT projects.
- true
MORYX;IIoT;IoT;Hardware;Communication;Manufacturing;Industrial;Abstraction;Realtime
diff --git a/src/Moryx.AbstractionLayer/Process/ProcessBindingResolverFactory.cs b/src/Moryx.AbstractionLayer/Process/ProcessBindingResolverFactory.cs
index 85ad9684a..2359bdbd7 100644
--- a/src/Moryx.AbstractionLayer/Process/ProcessBindingResolverFactory.cs
+++ b/src/Moryx.AbstractionLayer/Process/ProcessBindingResolverFactory.cs
@@ -127,6 +127,10 @@ public class ProductResolver : BindingResolverBase
{
private readonly string _fallbackProperty;
+ ///
+ /// Creates a new
+ ///
+ ///
public ProductResolver(string fallbackProperty)
{
_fallbackProperty = fallbackProperty;
diff --git a/src/Moryx.AbstractionLayer/Resources/IPublicResource.cs b/src/Moryx.AbstractionLayer/Resources/IPublicResource.cs
deleted file mode 100644
index 0abe142e8..000000000
--- a/src/Moryx.AbstractionLayer/Resources/IPublicResource.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
-// Licensed under the Apache License, Version 2.0
-
-using System;
-using Moryx.AbstractionLayer.Capabilities;
-
-namespace Moryx.AbstractionLayer.Resources
-{
- ///
- /// Interface for resources that are visible outside of the abstraction layer
- ///
- public interface IPublicResource : IResource
- {
- ///
- /// The resource's capabilities
- ///
- ICapabilities Capabilities { get; }
-
- ///
- /// Raised when the capabilities have changed.
- ///
- event EventHandler CapabilitiesChanged;
- }
-}
diff --git a/src/Moryx.AbstractionLayer/Resources/IResource.cs b/src/Moryx.AbstractionLayer/Resources/IResource.cs
index 60bad43ec..112617ebe 100644
--- a/src/Moryx.AbstractionLayer/Resources/IResource.cs
+++ b/src/Moryx.AbstractionLayer/Resources/IResource.cs
@@ -1,6 +1,9 @@
// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0
+using Moryx.AbstractionLayer.Capabilities;
+using System;
+
namespace Moryx.AbstractionLayer.Resources
{
///
@@ -17,5 +20,15 @@ public interface IResource
/// Name of this resource instance
///
string Name { get; }
+
+ ///
+ /// The resource's capabilities
+ ///
+ ICapabilities Capabilities { get; }
+
+ ///
+ /// Raised when the capabilities have changed.
+ ///
+ event EventHandler CapabilitiesChanged;
}
}
diff --git a/src/Moryx.AbstractionLayer/Resources/IResourceManagement.cs b/src/Moryx.AbstractionLayer/Resources/IResourceManagement.cs
index 631a11cad..9e8bf7771 100644
--- a/src/Moryx.AbstractionLayer/Resources/IResourceManagement.cs
+++ b/src/Moryx.AbstractionLayer/Resources/IResourceManagement.cs
@@ -16,51 +16,51 @@ public interface IResourceManagement
/// Get only resources of this type
///
TResource GetResource()
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get typed resource by id
///
TResource GetResource(long id)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get typed resource by name
///
TResource GetResource(string name)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get the only resource that provides the required capabilities.
///
/// Instance if only one match was found, otherwise null
TResource GetResource(ICapabilities requiredCapabilities)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get the only resource that matches the given predicate
///
/// Instance if only one match was found, otherwise null
TResource GetResource(Func predicate)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get all resources of this type
///
IEnumerable GetResources()
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get all resources of this type that provide the required capabilities
///
IEnumerable GetResources(ICapabilities requiredCapabilities)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get all resources of this type that match the predicate
///
IEnumerable GetResources(Func predicate)
- where TResource : class, IPublicResource;
+ where TResource : class, IResource;
///
/// Get all resources inluding the private ones of this type that match the predicate
@@ -95,12 +95,12 @@ IEnumerable GetAllResources(Func predicat
///
/// Event raised when a resource was added at runtime
///
- event EventHandler ResourceAdded;
+ event EventHandler ResourceAdded;
///
/// Event raised when a resource was removed at runtime
///
- event EventHandler ResourceRemoved;
+ event EventHandler ResourceRemoved;
///
/// Raised when the capabilities have changed.
diff --git a/src/Moryx.AbstractionLayer/Resources/PublicResource.cs b/src/Moryx.AbstractionLayer/Resources/PublicResource.cs
deleted file mode 100644
index b098c5b02..000000000
--- a/src/Moryx.AbstractionLayer/Resources/PublicResource.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
-// Licensed under the Apache License, Version 2.0
-
-using System;
-using Moryx.AbstractionLayer.Capabilities;
-
-namespace Moryx.AbstractionLayer.Resources
-{
- ///
- /// Base class for all public resources
- ///
- public abstract class PublicResource : Resource, IPublicResource
- {
- ///
- /// Current capabilities of this resource
- ///
- private ICapabilities _capabilities = NullCapabilities.Instance;
-
- ///
- public ICapabilities Capabilities
- {
- get
- {
- return _capabilities;
- }
- protected set
- {
- _capabilities = value;
- CapabilitiesChanged?.Invoke(this, _capabilities);
- }
- }
-
- ///
- ///
- ///
- public event EventHandler CapabilitiesChanged;
- }
-}
diff --git a/src/Moryx.AbstractionLayer/Resources/Resource.cs b/src/Moryx.AbstractionLayer/Resources/Resource.cs
index edb9430bf..c2d520d2a 100644
--- a/src/Moryx.AbstractionLayer/Resources/Resource.cs
+++ b/src/Moryx.AbstractionLayer/Resources/Resource.cs
@@ -4,6 +4,7 @@
using System;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
+using Moryx.AbstractionLayer.Capabilities;
using Moryx.Logging;
using Moryx.Modules;
using Moryx.Serialization;
@@ -144,6 +145,31 @@ public override string ToString()
return $"{Id}:{Name} ({GetType().Name})";
}
+
+ ///
+ /// Current capabilities of this resource
+ ///
+ private ICapabilities _capabilities = NullCapabilities.Instance;
+
+ ///
+ public ICapabilities Capabilities
+ {
+ get
+ {
+ return _capabilities;
+ }
+ protected set
+ {
+ _capabilities = value;
+ CapabilitiesChanged?.Invoke(this, _capabilities);
+ }
+ }
+
+ ///
+ ///
+ ///
+ public event EventHandler CapabilitiesChanged;
+
///
/// Event raised when the resource was modified and the changes should be
/// written to the data storage
diff --git a/src/Moryx.Asp.Extensions/Moryx.Asp.Extensions.csproj b/src/Moryx.Asp.Extensions/Moryx.Asp.Extensions.csproj
index ea47f4474..27255d156 100644
--- a/src/Moryx.Asp.Extensions/Moryx.Asp.Extensions.csproj
+++ b/src/Moryx.Asp.Extensions/Moryx.Asp.Extensions.csproj
@@ -1,9 +1,8 @@
- net6.0
+ net8.0
Extensions for the Integration of MORYX in ASP.NET Core
- true
MORYX;ASP
diff --git a/src/Moryx.CommandCenter.Web/Moryx.CommandCenter.Web.csproj b/src/Moryx.CommandCenter.Web/Moryx.CommandCenter.Web.csproj
index 14400baae..9c00b3ba0 100644
--- a/src/Moryx.CommandCenter.Web/Moryx.CommandCenter.Web.csproj
+++ b/src/Moryx.CommandCenter.Web/Moryx.CommandCenter.Web.csproj
@@ -8,9 +8,8 @@
- net6.0
+ net8.0
true
- true
diff --git a/src/Moryx.CommandCenter.Web/package.json b/src/Moryx.CommandCenter.Web/package.json
index e5441ec98..19dba0c84 100644
--- a/src/Moryx.CommandCenter.Web/package.json
+++ b/src/Moryx.CommandCenter.Web/package.json
@@ -16,7 +16,7 @@
"@emotion/styled": "^11.11.5",
"@mdi/js": "^7.4.47",
"@mdi/react": "^1.6.1",
- "@mui/material": "^5.15.15",
+ "@mui/material": "^6.1.1",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@types/react-redux": "^7.1.33",
@@ -24,8 +24,8 @@
"moment": "^2.30.1",
"path-scurry": "^1.10.2",
"query-string": "^9.0.0",
- "react": "18.2.0",
- "react-dom": "18.2.0",
+ "react": "18.3.1",
+ "react-dom": "18.3.1",
"react-redux": "^9.1.0",
"react-router": "^6.22.0",
"react-router-dom": "^6.22.0",
@@ -41,11 +41,11 @@
"@types/react-router-redux": "^5.0.27",
"css-loader": "^6.10.0",
"html-webpack-plugin": "^5.6.0",
- "rimraf": "5.0.5",
+ "rimraf": "5.0.7",
"sass": "^1.72.0",
"sass-loader": "^14.1.0",
"source-map-loader": "^5.0.0",
- "style-loader": "^3.3.4",
+ "style-loader": "^4.0.0",
"tslint": "^6.1.3",
"tslint-loader": "^3.5.4",
"tslint-react": "^5.0.0",
diff --git a/src/Moryx.Communication.Serial/Moryx.Communication.Serial.csproj b/src/Moryx.Communication.Serial/Moryx.Communication.Serial.csproj
index 41dda1c2d..353b1adb0 100644
--- a/src/Moryx.Communication.Serial/Moryx.Communication.Serial.csproj
+++ b/src/Moryx.Communication.Serial/Moryx.Communication.Serial.csproj
@@ -1,10 +1,9 @@
- netstandard2.0;net6.0
+ netstandard2.0;net8.0
true
MORYX binary connection for serial communication
- true
MORYX;Communication;Serial;Ports
diff --git a/src/Moryx.Container/CastleContainer.cs b/src/Moryx.Container/CastleContainer.cs
index b1a12edd6..411a51257 100644
--- a/src/Moryx.Container/CastleContainer.cs
+++ b/src/Moryx.Container/CastleContainer.cs
@@ -18,107 +18,58 @@ namespace Moryx.Container
///
public class CastleContainer : IContainer
{
- ///
- /// Internal windsor container doing the real DI
- ///
- protected IWindsorContainer Container { get; private set; }
-
- ///
- /// Registrator used to evaluate attributes
- ///
- protected IComponentRegistrator Registrator { get; }
#region Constructors
+ private readonly IWindsorContainer _container;
+
+ private readonly IDictionary _strategies;
+
///
- /// Create new container instance with default registrator
+ /// Create instance without strategies
///
public CastleContainer()
- : this(new ComponentRegistrator())
+ : this(new Dictionary())
{
}
-
///
- /// Constructor to modify the applied registrator
+ /// Create container with strategies
///
- /// Registrator replacement
- internal CastleContainer(ComponentRegistrator registrator)
+ ///
+ public CastleContainer(IDictionary strategies)
{
- // Boot up the container and give it to the registrator
- Container = registrator.Container = new WindsorContainer();
- Registrator = registrator;
+ _strategies = strategies;
+
+ // Boot up the container
+ _container = new WindsorContainer();
- Container.AddFacility();
- Container.AddFacility();
+ _container.AddFacility();
+ _container.AddFacility(mf => mf.AddStrategies(strategies));
// Self registration for framework functionality
- SetInstance(this);
+ RegisterInstance(new[] { typeof(IContainer) }, this, null);
}
#endregion
- ///
- public virtual void Destroy()
- {
- Container.Dispose();
- Container = null;
- }
-
- ///
- /// Execute the installer for this assembly
- ///
- ///
- public IContainer ExecuteInstaller(IContainerInstaller installer)
- {
- installer.Install(Registrator);
-
- return this;
- }
-
- ///
- /// Resolve an instance of the given service
- ///
- /// Type to resolve
- /// Instance of type
- public virtual T Resolve()
- {
- return Container.Kernel.HasComponent(typeof(T)) ? Container.Resolve() : default(T);
- }
-
- ///
- /// Resolve this dependency
- ///
- public virtual object Resolve(Type service)
- {
- return Container.Kernel.HasComponent(service) ? Container.Resolve(service) : null;
- }
-
- ///
- /// Resolve a named instance of the given service
- ///
- /// Type to resolve
- /// Instance of type
- public T Resolve(string name)
- {
- return Container.Kernel.HasComponent(name) ? Container.Resolve(name) : default(T);
- }
-
///
/// Resolve this named dependency
///
public object Resolve(Type service, string name)
{
- return Container.Kernel.HasComponent(name) ? Container.Resolve(name, service) : null;
- }
+ if(name == null && _strategies.ContainsKey(service))
+ name = _strategies[service];
+
+ // Resolve by name if given or determined
+ if (name != null && _container.Kernel.HasComponent(name))
+ return _container.Resolve(name, service);
- ///
- /// Resolve all implementations of this contract
- ///
- /// Type to resolve
- ///
- public T[] ResolveAll()
- {
- return Container.ResolveAll();
+ // Resolve by type if found
+ if (_container.Kernel.HasComponent(service))
+ return _container.Resolve(service);
+
+ // Otherwise return null
+ return null;
}
///
@@ -126,153 +77,98 @@ public T[] ResolveAll()
///
public Array ResolveAll(Type service)
{
- return Container.ResolveAll(service);
+ return _container.ResolveAll(service);
}
///
/// Get all implementations for a given component interface
///
///
- public IEnumerable GetRegisteredImplementations(Type componentInterface)
+ public IEnumerable GetRegisteredImplementations(Type service)
{
- return Container.Kernel.GetHandlers(componentInterface).Select(handler => handler.ComponentModel.Implementation);
+ return _container.Kernel.GetHandlers(service).Select(handler => handler.ComponentModel.Implementation);
}
- #region LoadComponents
- private static Type[] _knownTypes;
+ #region Register methods
///
- /// Load all implementations of type from currently known types
- /// KnownTypes: Types in default framework folders and deeper.
+ /// Register a component in the container
///
- public void LoadComponents() where T : class
+ public void Register(Type type, Type[] services, string name, LifeCycle lifeCycle)
{
- LoadComponents(null);
- }
+ // Make sure component is not registered yet
+ var componentName = name ?? type.FullName;
+ if (_container.Kernel.HasComponent(componentName))
+ return;
- ///
- /// Loads all implementations of type from the currently known types
- /// KnownTypes: Types in default framework folders and deeper.
- ///
- public virtual void LoadComponents(Predicate condition) where T : class
- {
- if (_knownTypes == null)
+ var registration = Component.For(services).ImplementedBy(type);
+
+ // Register name
+ if (!string.IsNullOrEmpty(name))
{
- _knownTypes = ReflectionTool.GetAssemblies()
- .Where(a => a.GetCustomAttribute() == null)
- .SelectMany(a =>
- {
- // TODO: Replace with exported types in MORYX 8
- try
- {
- // This should only return exported types
- return a.GetTypes();
- }
- catch
- {
- // Fall back to exported types in case of exception
- try
- {
- return a.GetExportedTypes();
- }
- catch
- {
- // Give up
- return new Type[0];
- }
- }
- })
- .Where(t => t.GetCustomAttribute(true) != null).ToArray();
+ registration.Named(name);
}
- foreach (var type in _knownTypes.Where(type => typeof(T).IsAssignableFrom(type)))
+ // Register life style
+ switch (lifeCycle)
{
- if(Registrator.ShallInstall(type) && (condition?.Invoke(type) ?? true))
- Registrator.Register(type);
+ case LifeCycle.Transient:
+ registration.LifestyleTransient();
+ break;
+ case LifeCycle.Singleton:
+ registration.LifestyleSingleton();
+ break;
}
- }
- #endregion
-
- #region Register methods
-
- ///
- public IContainer Register()
- where TService : class
- where TComp : TService
- {
- Registrator.Register(typeof(TComp), new[] { typeof(TService) });
- return this;
- }
-
- ///
- public IContainer Register(string name, LifeCycle lifeCycle)
- where TService : class
- where TComp : TService
- {
- Registrator.Register(typeof(TComp), new[] { typeof(TService) }, name, lifeCycle);
- return this;
+ _container.Register(registration);
}
- ///
- public IContainer Register() where TFactory : class
- {
- Registrator.RegisterFactory(typeof(TFactory));
- return this;
- }
-
- ///
- public IContainer Register(string name) where TFactory : class
- {
- var factoryType = typeof(TFactory);
- var att = typeof(TFactory).GetCustomAttribute();
- Registrator.RegisterFactory(factoryType, name, att?.Selector);
- return this;
- }
-
- #endregion
-
- #region SetInstances
-
///
- /// Set instance of service
+ /// Register factory interface
///
- /// Type of service
- /// Instance implementing the service
- public IContainer SetInstance(T instance) where T : class
+ public void RegisterFactory(Type factoryInterface, string name, Type selector)
{
- if (instance != null)
+ var registration = Component.For(factoryInterface);
+
+ if (!string.IsNullOrEmpty(name))
{
- Container.Register(Component.For().Instance(instance));
+ registration.Named(name);
}
- return this;
- }
- ///
- /// Set globally imported instance with name
- ///
- /// Type of service
- /// Instance to register
- /// Name of instance
- public IContainer SetInstance(T instance, string name) where T : class
- {
- if (instance != null)
+ if (selector == null)
+ {
+ registration.AsFactory();
+ }
+ else
{
- Container.Register(Component.For().Instance(instance).Named(name));
+ // Make sure selector is registered in the container
+ // TODO: Super dirty hack to use interfaces in component selectors
+ var selectorName = selector.IsClass ? selector.FullName : $"{selector.Namespace}.{selector.Name.Substring(1)}";
+ registration.AsFactory(config => config.SelectedWith(selectorName));
}
- return this;
+
+ _container.Register(registration);
}
- public void Extend() where TExtension : new()
+ ///
+ /// Register instance in the container
+ ///
+ public void RegisterInstance(Type[] services, object instance, string name)
{
- var facilityType = typeof(IFacility);
- if (!facilityType.IsAssignableFrom(typeof(TExtension)))
- throw new InvalidOperationException("The underlying container only supports " + facilityType.FullName + "!");
+ var registration = Component.For(services).Instance(instance);
+
+ if (!string.IsNullOrEmpty(name))
+ registration.Named(name);
- var facility = (IFacility)new TExtension();
- Container.AddFacility(facility);
+ _container.Register(registration);
}
#endregion
+
+ ///
+ public virtual void Destroy()
+ {
+ _container.Dispose();
+ }
}
}
diff --git a/src/Moryx.Container/ChildContainerSubResolver.cs b/src/Moryx.Container/ChildContainerSubResolver.cs
index 6e6275d24..d39dd5148 100644
--- a/src/Moryx.Container/ChildContainerSubResolver.cs
+++ b/src/Moryx.Container/ChildContainerSubResolver.cs
@@ -46,7 +46,7 @@ private static bool IsContainerChild(Type candidate)
return candidate.IsGenericType && candidate.GetGenericTypeDefinition() == typeof(IContainerChild<>);
}
- private UseChildAttribute GetAttribute(Type targetType, DependencyModel dependency)
+ private static UseChildAttribute GetAttribute(Type targetType, DependencyModel dependency)
{
UseChildAttribute att = null;
if (dependency.IsOptional)
diff --git a/src/Moryx.Container/Installer/AutoInstaller.cs b/src/Moryx.Container/Installer/AutoInstaller.cs
deleted file mode 100644
index ef772eed2..000000000
--- a/src/Moryx.Container/Installer/AutoInstaller.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
-// Licensed under the Apache License, Version 2.0
-
-using System;
-using System.Reflection;
-
-namespace Moryx.Container
-{
- ///
- /// Installer for automatic registration
- ///
- public class AutoInstaller : IContainerInstaller
- {
- private readonly Assembly _targetAssembly;
-
- ///
- /// Create a new instance of the for this assembly
- ///
- public AutoInstaller(Assembly targetAssembly)
- {
- _targetAssembly = targetAssembly ?? GetType().Assembly;
- }
-
-
- ///
- /// Install components to the container
- ///
- /// Registrator to register new types
- public virtual void Install(IComponentRegistrator registrator)
- {
- // Install all components
- foreach (var type in _targetAssembly.GetTypes())
- {
- // Register all we want
- if (ShallInstall(registrator, type))
- registrator.Register(type);
- }
- }
-
- ///
- /// Method to determine if this component shall be installed
- ///
- protected internal virtual bool ShallInstall(IComponentRegistrator registrator, Type foundType)
- {
- return registrator.ShallInstall(foundType);
- }
- }
-}
diff --git a/src/Moryx.Container/Installer/ComponentRegistrator.cs b/src/Moryx.Container/Installer/ComponentRegistrator.cs
deleted file mode 100644
index fc05ca508..000000000
--- a/src/Moryx.Container/Installer/ComponentRegistrator.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
-// Licensed under the Apache License, Version 2.0
-
-using System;
-using System.Linq;
-using System.Reflection;
-using Castle.Facilities.TypedFactory;
-using Castle.MicroKernel.Registration;
-using Castle.Windsor;
-
-namespace Moryx.Container
-{
- internal class ComponentRegistrator : IComponentRegistrator
- {
- ///
- /// Internal windsor container for registration
- ///
- protected internal IWindsorContainer Container { get; set; }
-
- ///
- /// Method to determine if this component shall be installed
- ///
- public virtual bool ShallInstall(Type foundType)
- {
- var regAtt = foundType.GetCustomAttribute();
- var facAtt = foundType.GetCustomAttribute();
-
- return (regAtt != null || facAtt != null) && NotRegisteredYet(foundType, regAtt);
- }
-
- ///
- /// Check if the type was not registered yet
- ///
- /// Type that must be checked for suitability to register
- ///
- /// True if the component was not registered before
- protected bool NotRegisteredYet(Type foundType, RegistrationAttribute regAtt)
- {
- var name = string.IsNullOrEmpty(regAtt?.Name) ? foundType.FullName : regAtt.Name;
- return !Container.Kernel.HasComponent(name);
- }
-
- public void Register(Type type)
- {
- if (type.IsInterface)
- {
- RegisterFactory(type);
- }
- else
- {
- Register(type, GetComponentServices(type));
- }
- }
-
- ///
- /// Get all services of this component
- ///
- public static Type[] GetComponentServices(Type type)
- {
- var att = type.GetCustomAttribute();
- if (att != null)
- return att.Services.Any() ? att.Services : new[] { type };
-
- var interfaces = type.GetInterfaces();
- return interfaces.Any() ? interfaces : new[] { type };
- }
-
- public void Register(Type type, Type[] services)
- {
- var regAtt = type.GetCustomAttribute();
- Register(type, services, regAtt?.Name, regAtt?.LifeStyle ?? LifeCycle.Singleton);
- }
-
-
- public void Register(Type type, Type[] services, string name)
- {
- Register(type, services, name, LifeCycle.Singleton);
- }
-
-
- public void Register(Type type, Type[] services, string name, LifeCycle lifeCycle)
- {
- var registration = BuildRegistration(type, services, name, lifeCycle);
-
- Container.Register(registration);
- }
-
- ///
- /// Build registration from arguments
- ///
- protected virtual ComponentRegistration