I am writing a series of plugins to be able to perform a specific set of actions as needed. I have been following the Microsoft documentation that can be found here: https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support. The basic examples work as expected, however, a more complex example does not. It should be noted that I copy the contents of the build into a temp folder to read in the plugins. I also believe I have been marking the project files correctly for plugins (excluding assets, enabling dynamic loading)
WORKING SCENARIO
Here is the basic interface that will be used by two plugins at runtime. It will be kept in its own assembly (PluginBase.csproj)
// IBusinessMethod.cs
namespace PluginBase
{
public interface IBusinessMethod
{
string Name { get; }
string Description { get; }
bool DoWork();
}
}
<!-- PluginBase.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Next is the sample of the code of one of the plugins. It is in an assembly which references only the PluginBase project (for the IBusinessMethod interface). The sample I have has another plugin almost identical to this one, but I am omitting it for brevity.
// CreateNewBusiness.cs
using PluginBase;
namespace CreateNewBusinessPlugin
{
public class CreateNewBusiness : IBusinessMethod
{
public string Name => "Create New Business";
public string Description => "Adds new business to multiple data repositories";
public bool DoWork()
{
Console.WriteLine("Business Added to 3 repos");
return true;
}
}
}
Here is the CreateNewBusinessPlugin.csproj file for reference:
<!-- CreateNewBusinessPlugin.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="set pluginpath="C:\temp\plugins\NewBusiness"
rmdir %25pluginpath%25 /S /Q
mkdir %25pluginpath%25
xcopy "$(OutDir)*.*" %25pluginpath%25 /E /Y /C" />
</Target>
<ItemGroup>
<ProjectReference Include="..\PluginBase\PluginBase.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>
The output from running this is here (successful run).
Loading commands from: C:\Temp\plugins\NewBusiness\CreateNewBusinessPlugin.dll
Loading commands from: C:\Temp\plugins\EvaluateBusiness\EvaluateBusinessPlugin.dll
Commands:
Create New Business - Adds new business to multiple data repositories
Business Added to 3 repos
Evaluate Business - Checks business for conflicts
Evaluated 3 businesses
ERROR SCENARIO
I need to add a dependency into the plugin interface project (PluginBase.csproj). Specifically, Microsoft.Extensions.Logging.Abstractions. I am now adding an Init(ILoggerFactory) function. (This is just an example that shows the issue - I am aware of .NET Hosting DI)
using Microsoft.Extensions.Logging;
namespace PluginBase
{
public interface IBusinessMethod
{
string Name { get; }
string Description { get; }
bool DoWork();
void Init(ILoggerFactory loggerFactory);
}
}
<!-- PluginBase.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.3" />
</ItemGroup>
</Project>
Now here I implement the interface in the CreateNewBusiness.cs and CreateNewBusinessPlugin.csproj files:
using Microsoft.Extensions.Logging;
using PluginBase;
namespace CreateNewBusinessPlugin
{
public class CreateNewBusiness : IBusinessMethod
{
ILogger<CreateNewBusiness> _logger;
public string Name => "Create New Business";
public string Description => "Adds new business to multiple data repositories";
public bool DoWork()
{
Console.WriteLine("Business Added to 3 repos");
return true;
}
public void Init(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<CreateNewBusiness>();
return;
}
}
}
<!-- CreateNewBusinessPlugin.csproj-->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="set pluginpath="C:\temp\plugins\NewBusiness"
rmdir %25pluginpath%25 /S /Q
mkdir %25pluginpath%25
xcopy "$(OutDir)*.*" %25pluginpath%25 /E /Y /C" />
</Target>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PluginBase\PluginBase.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>
The resulting output:
Loading commands from: C:\Temp\plugins\NewBusiness\CreateNewBusinessPlugin.dll
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Method 'Init' in type 'CreateNewBusinessPlugin.CreateNewBusiness' from assembly 'CreateNewBusinessPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()
at MyPluginApp.Program.CreateCommands(Assembly assembly)+MoveNext() in C:\Users\jipoc\source\repos\MyPluginApp\MyPluginApp\Program.cs:line 93
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at MyPluginApp.Program.Main(String[] args) in C:\Users\jipoc\source\repos\MyPluginApp\MyPluginApp\Program.cs:line 35
System.TypeLoadException: Method 'Init' in type 'CreateNewBusinessPlugin.CreateNewBusiness' from assembly 'CreateNewBusinessPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
The error indicates that the new Init function is not implemented. However, going into the folder containing the plugin and using ILSpy, I get this:
// CreateNewBusinessPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// CreateNewBusinessPlugin.CreateNewBusiness
using System;
using CreateNewBusinessPlugin;
using Microsoft.Extensions.Logging;
using PluginBase;
public class CreateNewBusiness : IBusinessMethod
{
private ILogger<CreateNewBusiness> _logger;
public string Name => "Create New Business";
public string Description => "Adds new business to multiple data repositories";
public bool DoWork()
{
Console.WriteLine("Business Added to 3 repos");
return true;
}
public void Init(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<CreateNewBusiness>();
}
}
Clearly, it IS impemented, but the loader does not see it as being implemented. And below is an image of that directory (which also includes the abstractions dll)

Why can the plug-in loader not recognize the new function?? I can post my whole solution somewhere, if it would help. I don't suspect the actual loader assembly / project, as it functions just fine without the Init function and is mostly a copy from the dotnet repo sample.
Any help would be appreciated.
Thank you!