Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/Blake.BuildTools/Utils/PluginLoadContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@ namespace Blake.BuildTools.Utils;
/// A custom AssemblyLoadContext that provides isolated plugin loading with dependency resolution.
/// Each plugin gets its own load context to avoid dependency conflicts.
/// </summary>
internal class PluginLoadContext : AssemblyLoadContext
internal class PluginLoadContext(string pluginPath) : AssemblyLoadContext(isCollectible: true)
{
private readonly AssemblyDependencyResolver _resolver;

public PluginLoadContext(string pluginPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
}
private readonly AssemblyDependencyResolver _resolver = new(pluginPath);

protected override Assembly? Load(AssemblyName assemblyName)
{
Expand Down
3 changes: 1 addition & 2 deletions src/Blake.BuildTools/Utils/PluginLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,7 @@ private static void LoadPluginDLLs(List<string> files, List<PluginContext> plugi
{
// Create a new load context for this plugin to resolve its dependencies
var loadContext = new PluginLoadContext(file);
var assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(file));
var assembly = loadContext.LoadFromAssemblyName(assemblyName);
var assembly = loadContext.LoadFromAssemblyPath(file);

var pluginTypes = assembly.GetTypes()
.Where(t => typeof(IBlakePlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Blake.BuildTools;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

namespace BlakePlugin.TestPluginWithDependencies;

Expand All @@ -10,15 +11,27 @@ public Task BeforeBakeAsync(BlakeContext context, ILogger? logger = null)
{
logger?.LogInformation("TestPluginWithDependencies: BeforeBakeAsync called");

// Use Newtonsoft.Json to test dependency loading
var testObject = new { Message = "Plugin with dependencies loaded successfully", PageCount = context.MarkdownPages.Count };
var serialized = JsonConvert.SerializeObject(testObject);
// Use SixLabors.ImageSharp to test dependency loading
using var image = new Image<Rgba32>(100, 100);
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
var row = accessor.GetRowSpan(y);
for (int x = 0; x < row.Length; x++)
{
row[x] = Color.Blue;
}
}
});

logger?.LogInformation("TestPluginWithDependencies: Serialized data: {SerializedData}", serialized);
var testMessage = $"Plugin with dependencies loaded successfully. Created {image.Width}x{image.Height} image. PageCount: {context.MarkdownPages.Count}";

logger?.LogInformation("TestPluginWithDependencies: {TestMessage}", testMessage);

// Create a marker file to prove the plugin ran with dependencies
var testFilePath = Path.Combine(context.ProjectPath, ".plugin-with-deps-before-bake.txt");
File.WriteAllText(testFilePath, serialized);
File.WriteAllText(testFilePath, testMessage);

return Task.CompletedTask;
}
Expand All @@ -27,12 +40,12 @@ public Task AfterBakeAsync(BlakeContext context, ILogger? logger = null)
{
logger?.LogInformation("TestPluginWithDependencies: AfterBakeAsync called with {PageCount} generated pages", context.GeneratedPages.Count);

// Use Newtonsoft.Json again to ensure dependency is still available
var testObject = new { Message = "Plugin dependencies working in AfterBakeAsync", GeneratedPageCount = context.GeneratedPages.Count };
var serialized = JsonConvert.SerializeObject(testObject);
// Use SixLabors.ImageSharp again to ensure dependency is still available
using var image = new Image<Rgba32>(50, 50);
var testMessage = $"Plugin dependencies working in AfterBakeAsync. Created {image.Width}x{image.Height} image. GeneratedPageCount: {context.GeneratedPages.Count}";

var testFilePath = Path.Combine(context.ProjectPath, ".plugin-with-deps-after-bake.txt");
File.WriteAllText(testFilePath, serialized);
File.WriteAllText(testFilePath, testMessage);

return Task.CompletedTask;
}
Expand Down