1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-07 13:48:00 -05:00

support hot reload of plugin code in debug configuration

This commit is contained in:
RaidMax 2024-08-27 10:10:58 -05:00
parent ac9c26817d
commit e956ab4d1a
No known key found for this signature in database
GPG Key ID: 97D1158CFCDAF9B2
6 changed files with 88 additions and 6 deletions

View File

@ -55,6 +55,7 @@
<ProjectReference Include="..\Integrations\Cod\Integrations.Cod.csproj" /> <ProjectReference Include="..\Integrations\Cod\Integrations.Cod.csproj" />
<ProjectReference Include="..\Integrations\Source\Integrations.Source.csproj" /> <ProjectReference Include="..\Integrations\Source\Integrations.Source.csproj" />
<ProjectReference Include="..\Data\Data.csproj" /> <ProjectReference Include="..\Data\Data.csproj" />
<ProjectReference Include="..\PluginDebugReference\PluginDebugReference.csproj" Condition="'$(Configuration)'=='Debug'"/>
<ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj"> <ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
@ -73,8 +74,8 @@
</None> </None>
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(ConfigurationName)'=='Debug'"> <!--<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(ConfigurationName)'=='Debug'">
<Exec Command="powershell.exe $(ProjectDir)BuildScripts\PreBuild.ps1 $(SolutionDir) $(TargetDir)" /> <Exec Command="powershell.exe $(ProjectDir)BuildScripts\PreBuild.ps1 $(SolutionDir) $(TargetDir)" />
</Target> </Target>-->
</Project> </Project>

View File

@ -38,6 +38,9 @@ using ILogger = Microsoft.Extensions.Logging.ILogger;
using IW4MAdmin.Plugins.Stats.Client.Abstractions; using IW4MAdmin.Plugins.Stats.Client.Abstractions;
using IW4MAdmin.Plugins.Stats.Client; using IW4MAdmin.Plugins.Stats.Client;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
#if DEBUG
using PluginDebugReference;
#endif
using Refit; using Refit;
using SharedLibraryCore.Interfaces.Events; using SharedLibraryCore.Interfaces.Events;
using Stats.Client.Abstractions; using Stats.Client.Abstractions;
@ -129,6 +132,10 @@ namespace IW4MAdmin.Application
Utilities.DefaultLogger = logger; Utilities.DefaultLogger = logger;
logger.LogInformation("Begin IW4MAdmin startup. Version is {Version}", Version); logger.LogInformation("Begin IW4MAdmin startup. Version is {Version}", Version);
#if DEBUG
StrongReferencesLoader.Load();
#endif
try try
{ {
// do any needed housekeeping file/folder migrations // do any needed housekeeping file/folder migrations

View File

@ -5,6 +5,9 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using IW4MAdmin.Application.API.Master; using IW4MAdmin.Application.API.Master;
#if DEBUG
using Microsoft.Extensions.DependencyModel;
#endif
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
@ -102,13 +105,27 @@ namespace IW4MAdmin.Application.Plugin
return (pluginTypes, commandTypes, configurationTypes); return (pluginTypes, commandTypes, configurationTypes);
} }
#if DEBUG
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().Select(asm => asm.GetName().Name);
var references = DependencyContext.Default?.GetDefaultAssemblyNames().Select(x => x.Name) ?? [];
var validAssemblies = references.Except(loadedAssemblies)
.Where(asm => !asm.StartsWith("Microsoft"))
.Where(asm => !asm.StartsWith("System"))
.Distinct();
var reloadableAssemblies = validAssemblies.Select(Assembly.Load);
#endif
// we only want to load the most recent assembly in case of duplicates // we only want to load the most recent assembly in case of duplicates
var assemblies = dllFileNames.Select(Assembly.LoadFrom) var assemblies = dllFileNames.Select(fileName => fileName).Select(Assembly.LoadFrom)
.Union(GetRemoteAssemblies()) .Union(GetRemoteAssemblies())
#if DEBUG
.Union(reloadableAssemblies)
#endif
.GroupBy(assembly => assembly.FullName).Select(assembly => .GroupBy(assembly => assembly.FullName).Select(assembly =>
assembly.OrderByDescending(asm => asm.GetName().Version).First()); assembly.OrderByDescending(asm => asm.GetName().Version).First());
var eligibleAssemblyTypes = assemblies var eligibleAssemblyTypes = assemblies.Concat(AppDomain.CurrentDomain.GetAssemblies()
.Where(asm => !new[] { "IW4MAdmin", "SharedLibraryCore" }.Contains(asm.GetName().Name)))
.SelectMany(asm => .SelectMany(asm =>
{ {
try try
@ -122,7 +139,7 @@ namespace IW4MAdmin.Application.Plugin
}).Where(type => }).Where(type =>
FilterTypes.Any(filterType => type.GetInterface(filterType.Name, false) != null) || FilterTypes.Any(filterType => type.GetInterface(filterType.Name, false) != null) ||
(type.IsClass && FilterTypes.Contains(type.BaseType))); (type.IsClass && FilterTypes.Contains(type.BaseType)));
foreach (var assemblyType in eligibleAssemblyTypes) foreach (var assemblyType in eligibleAssemblyTypes)
{ {
var isPlugin = var isPlugin =
@ -193,7 +210,7 @@ namespace IW4MAdmin.Application.Plugin
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning(ex,"Could not load remote scripts"); _logger.LogWarning(ex, "Could not load remote scripts");
return Enumerable.Empty<string>(); return Enumerable.Empty<string>();
} }
} }

View File

@ -52,6 +52,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ScriptPlugins", "ScriptPlug
Plugins\ScriptPlugins\ServerBanner.js = Plugins\ScriptPlugins\ServerBanner.js Plugins\ScriptPlugins\ServerBanner.js = Plugins\ScriptPlugins\ServerBanner.js
Plugins\ScriptPlugins\ParserBOIII.js = Plugins\ScriptPlugins\ParserBOIII.js Plugins\ScriptPlugins\ParserBOIII.js = Plugins\ScriptPlugins\ParserBOIII.js
Plugins\ScriptPlugins\ParserL4D2SM.js = Plugins\ScriptPlugins\ParserL4D2SM.js Plugins\ScriptPlugins\ParserL4D2SM.js = Plugins\ScriptPlugins\ParserL4D2SM.js
Plugins\ScriptPlugins\ParserPlutoniumT6.js = Plugins\ScriptPlugins\ParserPlutoniumT6.js
Plugins\ScriptPlugins\ParserH2MMOD.js = Plugins\ScriptPlugins\ParserH2MMOD.js
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutomessageFeed", "Plugins\AutomessageFeed\AutomessageFeed.csproj", "{F5815359-CFC7-44B4-9A3B-C04BACAD5836}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutomessageFeed", "Plugins\AutomessageFeed\AutomessageFeed.csproj", "{F5815359-CFC7-44B4-9A3B-C04BACAD5836}"
@ -115,6 +117,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GithubActions", "GithubActi
.github\workflows\shared_library_nuget.yml = .github\workflows\shared_library_nuget.yml .github\workflows\shared_library_nuget.yml = .github\workflows\shared_library_nuget.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginDebugReference", "PluginDebugReference\PluginDebugReference.csproj", "{2EB30B9B-FEC4-4A30-A955-515D55D0555B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -443,6 +447,30 @@ Global
{259824F3-D860-4233-91D6-FF73D4DD8B18}.Release|x86.Build.0 = Release|Any CPU {259824F3-D860-4233-91D6-FF73D4DD8B18}.Release|x86.Build.0 = Release|Any CPU
{259824F3-D860-4233-91D6-FF73D4DD8B18}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU {259824F3-D860-4233-91D6-FF73D4DD8B18}.Prerelease|Any CPU.ActiveCfg = Prerelease|Any CPU
{259824F3-D860-4233-91D6-FF73D4DD8B18}.Prerelease|Any CPU.Build.0 = Prerelease|Any CPU {259824F3-D860-4233-91D6-FF73D4DD8B18}.Prerelease|Any CPU.Build.0 = Prerelease|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|x64.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|x64.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|x86.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Debug|x86.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|Any CPU.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|Any CPU.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|Mixed Platforms.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|x64.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|x64.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|x86.ActiveCfg = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Prerelease|x86.Build.0 = Debug|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|Any CPU.Build.0 = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|x64.ActiveCfg = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|x64.Build.0 = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|x86.ActiveCfg = Release|Any CPU
{2EB30B9B-FEC4-4A30-A955-515D55D0555B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Plugins\AutomessageFeed\AutomessageFeed.csproj" />
<ProjectReference Include="..\Plugins\LiveRadar\LiveRadar.csproj" />
<ProjectReference Include="..\Plugins\Login\Login.csproj" />
<ProjectReference Include="..\Plugins\Mute\Mute.csproj" />
<ProjectReference Include="..\Plugins\ProfanityDeterment\ProfanityDeterment.csproj" />
<ProjectReference Include="..\Plugins\Stats\Stats.csproj" />
<ProjectReference Include="..\Plugins\Welcome\Welcome.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@

namespace PluginDebugReference;
public static class StrongReferencesLoader
{
public static void Load()
{
// only for explicit reference
}
}