From 15d1b6b4c8526d8be63b1c97b7865e67df991ee3 Mon Sep 17 00:00:00 2001
From: CalvinWilkinson <kinsondigital@gmail.com>
Date: Mon, 27 Jan 2025 18:27:58 +0000
Subject: [PATCH] refactor: move application class code to assembly code

---
 CASL/Application.cs                           | 24 -------------------
 CASL/DotnetWrappers/Assembly.cs               |  5 ++++
 CASL/DotnetWrappers/IAssembly.cs              |  5 ++++
 CASL/IApplication.cs                          | 16 -------------
 CASL/IoC.cs                                   |  1 -
 CASL/NativeInterop/NativeLibraryLoader.cs     | 15 ++++++------
 CASL/NativeInterop/OpenALLibrary.cs           | 14 +++++++----
 .../NativeInterop/OpenALLibraryTests.cs       | 16 ++++++-------
 8 files changed, 34 insertions(+), 62 deletions(-)
 delete mode 100644 CASL/Application.cs
 delete mode 100644 CASL/IApplication.cs

diff --git a/CASL/Application.cs b/CASL/Application.cs
deleted file mode 100644
index e64d306b..00000000
--- a/CASL/Application.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// <copyright file="Application.cs" company="KinsonDigital">
-// Copyright (c) KinsonDigital. All rights reserved.
-// </copyright>
-
-namespace CASL;
-
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-
-/// <summary>
-/// Provides information about the running application.
-/// </summary>
-[ExcludeFromCodeCoverage(Justification = "Directly interacts with dotnet.")]
-internal sealed class Application : IApplication
-{
-    /// <summary>
-    /// Initializes a new instance of the <see cref="Application"/> class.
-    /// </summary>
-    public Application() => this.Location = AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar);
-
-    /// <inheritdoc/>
-    public string Location { get; }
-}
diff --git a/CASL/DotnetWrappers/Assembly.cs b/CASL/DotnetWrappers/Assembly.cs
index 13969da7..9d731472 100644
--- a/CASL/DotnetWrappers/Assembly.cs
+++ b/CASL/DotnetWrappers/Assembly.cs
@@ -6,6 +6,7 @@ namespace CASL.DotnetWrappers;
 
 using System;
 using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Runtime.Loader;
 
 /// <inheritdoc cref="IAssembly"/>
@@ -20,6 +21,7 @@ internal sealed class Assembly : IAssembly, IDisposable
     /// </summary>
     public Assembly()
     {
+        this.Location = AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar);
         var assembly = System.Reflection.Assembly.GetExecutingAssembly();
 
         ArgumentNullException.ThrowIfNull(assembly);
@@ -32,6 +34,9 @@ public Assembly()
     /// <inheritdoc/>
     public event Action? Unloading;
 
+    /// <inheritdoc/>
+    public string Location { get; }
+
     /// <inheritdoc cref="IDisposable.Dispose"/>
     public void Dispose() => Dispose(true);
 
diff --git a/CASL/DotnetWrappers/IAssembly.cs b/CASL/DotnetWrappers/IAssembly.cs
index f0489d46..2ebfaff7 100644
--- a/CASL/DotnetWrappers/IAssembly.cs
+++ b/CASL/DotnetWrappers/IAssembly.cs
@@ -15,4 +15,9 @@ internal interface IAssembly
     /// Occurs when the assembly is unloading.
     /// </summary>
     event Action Unloading;
+
+    /// <summary>
+    /// Gets the file path of the current assembly.
+    /// </summary>
+    string Location { get; }
 }
diff --git a/CASL/IApplication.cs b/CASL/IApplication.cs
deleted file mode 100644
index c6cf54ee..00000000
--- a/CASL/IApplication.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// <copyright file="IApplication.cs" company="KinsonDigital">
-// Copyright (c) KinsonDigital. All rights reserved.
-// </copyright>
-
-namespace CASL;
-
-/// <summary>
-/// Provides information about the running application.
-/// </summary>
-internal interface IApplication
-{
-    /// <summary>
-    /// Gets the file path of the current application.
-    /// </summary>
-    string Location { get; }
-}
diff --git a/CASL/IoC.cs b/CASL/IoC.cs
index ea3a1e07..387692ab 100644
--- a/CASL/IoC.cs
+++ b/CASL/IoC.cs
@@ -65,7 +65,6 @@ private static void SetupContainer()
         IoCContainer.Register<IAssembly, Assembly>(Lifestyle.Singleton);
         IoCContainer.Register<ITaskService, TaskService>(true);
         IoCContainer.Register<IThreadService, ThreadService>(Lifestyle.Singleton);
-        IoCContainer.Register<IApplication, Application>(Lifestyle.Singleton);
         IoCContainer.Register<IPlatform, Platform>(Lifestyle.Singleton);
         IoCContainer.Register<ILibrary, OpenALLibrary>(Lifestyle.Singleton);
         IoCContainer.Register<IDelegateFactory, DelegateFactory>(Lifestyle.Singleton);
diff --git a/CASL/NativeInterop/NativeLibraryLoader.cs b/CASL/NativeInterop/NativeLibraryLoader.cs
index 50c8bbbd..432ed82b 100644
--- a/CASL/NativeInterop/NativeLibraryLoader.cs
+++ b/CASL/NativeInterop/NativeLibraryLoader.cs
@@ -14,6 +14,7 @@ namespace CASL.NativeInterop;
 using System;
 using System.IO;
 using System.IO.Abstractions;
+using DotnetWrappers;
 using Exceptions;
 
 /// <summary>
@@ -21,38 +22,36 @@ namespace CASL.NativeInterop;
 /// </summary>
 internal sealed class NativeLibraryLoader : ILibraryLoader
 {
-    private readonly IApplication application;
+    private readonly IAssembly assembly;
     private readonly IPlatform platform;
-    private readonly IDirectory directory;
     private readonly IFile file;
     private readonly IPath path;
 
     /// <summary>
     /// Initializes a new instance of the <see cref="NativeLibraryLoader"/> class.
     /// </summary>
+    /// <param name="assembly">Provides assembly related services.</param>
     /// <param name="platform">Provides platform specific information.</param>
-    /// <param name="directory">Performs operations with directories.</param>
     /// <param name="file">Performs operations with files.</param>
     /// <param name="path">Manages file paths.</param>
     /// <param name="library">The library to load.</param>
     public NativeLibraryLoader(
-        IApplication application,
+        IAssembly assembly,
         IPlatform platform,
         IDirectory directory,
         IFile file,
         IPath path,
         ILibrary library)
     {
-        ArgumentNullException.ThrowIfNull(application);
+        ArgumentNullException.ThrowIfNull(assembly);
         ArgumentNullException.ThrowIfNull(platform);
         ArgumentNullException.ThrowIfNull(directory);
         ArgumentNullException.ThrowIfNull(file);
         ArgumentNullException.ThrowIfNull(path);
         ArgumentNullException.ThrowIfNull(library);
 
-        this.application = application;
+        this.assembly = assembly;
         this.platform = platform;
-        this.directory = directory;
         this.file = file;
         this.path = path;
 
@@ -65,7 +64,7 @@ public NativeLibraryLoader(
     /// <inheritdoc/>
     public nint LoadLibrary()
     {
-        var libDirPath = this.application.Location;
+        var libDirPath = this.assembly.Location;
         var libFilePath = $"{libDirPath}{this.path.DirectorySeparatorChar}{LibraryName}";
 
         var (exists, libPtr) = LoadLibraryIfExists(libFilePath);
diff --git a/CASL/NativeInterop/OpenALLibrary.cs b/CASL/NativeInterop/OpenALLibrary.cs
index 8a833c06..8a36dc39 100644
--- a/CASL/NativeInterop/OpenALLibrary.cs
+++ b/CASL/NativeInterop/OpenALLibrary.cs
@@ -6,6 +6,7 @@ namespace CASL.NativeInterop;
 
 using System.IO;
 using System.IO.Abstractions;
+using DotnetWrappers;
 using Exceptions;
 
 /// <summary>
@@ -25,20 +26,23 @@ internal sealed class OpenALLibrary : ILibrary
     /// Initializes a new instance of the <see cref="OpenALLibrary"/> class.
     /// </summary>
     /// <param name="platform">Provides platform specific information.</param>
-    /// <param name="application">Provides application related services.</param>
+    /// <param name="directory">Performs operations with directories.</param>
+    /// <param name="file">Performs operations with files.</param>
+    /// <param name="path">Manages file paths.</param>
+    /// <param name="assembly">Provides assembly related services.</param>
     public OpenALLibrary(
         IPlatform platform,
         IDirectory directory,
         IFile file,
         IPath path,
-        IApplication application)
+        IAssembly assembly)
     {
         // TODO: Add null checks for all params
         this.platform = platform;
         this.directory = directory;
         this.file = file;
         this.path = path;
-        this.appDirPath = application.Location;
+        this.appDirPath = assembly.Location;
 
         ProcessLibFile();
     }
@@ -69,7 +73,7 @@ private void ProcessLibFile()
         var libName = GetLibraryName();
         var fullLibPath = $"{this.appDirPath}{this.path.DirectorySeparatorChar}{libName}";
 
-        // Check if the library exists in the same location as the application
+        // Check if the library exists in the same location as the assembly
         if (this.file.Exists(fullLibPath))
         {
             return;
@@ -103,7 +107,7 @@ private void ProcessLibFile()
             throw new FileNotFoundException($"The library '{libName}' does not exist in the platform directory '{platformDirPath}'.");
         }
 
-        // At this point, the library file exist.  Copy the library to the same location as the application.
+        // At this point, the library file exist.  Copy the library to the same location as the assembly.
         this.file.Copy(fullPlatLibPath, fullLibPath);
     }
 }
diff --git a/Testing/CASLTests/NativeInterop/OpenALLibraryTests.cs b/Testing/CASLTests/NativeInterop/OpenALLibraryTests.cs
index 77be724c..0f26a928 100644
--- a/Testing/CASLTests/NativeInterop/OpenALLibraryTests.cs
+++ b/Testing/CASLTests/NativeInterop/OpenALLibraryTests.cs
@@ -8,7 +8,7 @@ namespace CASLTests.NativeInterop;
 #pragma warning disable IDE0001 // The name can be simplified
 using System.IO;
 using System.IO.Abstractions;
-using CASL;
+using CASL.DotnetWrappers;
 using CASL.Exceptions;
 using CASL.NativeInterop;
 using Xunit;
@@ -26,7 +26,7 @@ public class OpenALLibraryTests
     private readonly IDirectory mockDirectory;
     private readonly IFile mockFile;
     private readonly IPath mockPath;
-    private readonly IApplication mockApplication;
+    private readonly IAssembly mockAssembly;
 
     /// <summary>
     /// Initializes a new instance of the <see cref="OpenALLibraryTests"/> class.
@@ -37,7 +37,7 @@ public OpenALLibraryTests()
         this.mockDirectory = Substitute.For<IDirectory>();
         this.mockFile = Substitute.For<IFile>();
         this.mockPath = Substitute.For<IPath>();
-        this.mockApplication = Substitute.For<IApplication>();
+        this.mockAssembly = Substitute.For<IAssembly>();
     }
 
 
@@ -65,7 +65,7 @@ public void Ctor_WhenPlatformDirPathDoesNotExist_ThrowsException()
     {
         // Arrange
         MockWindowsPlatform();
-        this.mockApplication.Location.Returns(@"C:\app-dir");
+        this.mockAssembly.Location.Returns(@"C:\app-dir");
         this.mockFile.Exists(Arg.Any<string>()).Returns(false);
         this.mockDirectory.Exists(Arg.Any<string>()).Returns(false);
 
@@ -84,7 +84,7 @@ public void Ctor_WhenFullPlatformLibFilePathDoesNotExist_ThrowsException()
         const string expected = @"The library 'soft_oal.dll' does not exist" +
                                 @" in the platform directory 'C:\app-dir\runtimes\win-x64\native'.";
         MockWindowsPlatform();
-        this.mockApplication.Location.Returns(@"C:\app-dir");
+        this.mockAssembly.Location.Returns(@"C:\app-dir");
         this.mockFile.Exists(Arg.Any<string>()).Returns(false);
         this.mockDirectory.Exists(Arg.Any<string>()).Returns(true);
 
@@ -172,7 +172,7 @@ private OpenALLibrary CreateSystemUnderTest()
             this.mockDirectory,
             this.mockFile,
             this.mockPath,
-            this.mockApplication);
+            this.mockAssembly);
 
     /// <summary>
     /// Mocks a windows platform.
@@ -182,7 +182,7 @@ private void MockWindowsPlatform()
         this.mockPlatform.IsWinPlatform().Returns(true);
         this.mockPlatform.IsPosixPlatform().Returns(false);
         this.mockPath.DirectorySeparatorChar.Returns('\\');
-        this.mockApplication.Location.Returns(@"C:\app-dir");
+        this.mockAssembly.Location.Returns(@"C:\app-dir");
     }
 
     /// <summary>
@@ -193,6 +193,6 @@ private void MockPosixPlatform()
         this.mockPlatform.IsWinPlatform().Returns(false);
         this.mockPlatform.IsPosixPlatform().Returns(true);
         this.mockPath.DirectorySeparatorChar.Returns('/');
-        this.mockApplication.Location.Returns("/app-dir");
+        this.mockAssembly.Location.Returns("/app-dir");
     }
 }