Here's one of the more obvious ways to achieve the result you seek (albeit not very secure, so you shouldn't allow that kind of approach if you rely on third party developers)
The general idea would be to locate and load the addon assemblies (addon developers should be able to implement an interface you provide them and package their code into a class library. When compiled, it produces DLL files).
It should be possible for your app to load an assembly knowing the path to the dll:
https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.loadfrom?view=netcore-3.1#System_Reflection_Assembly_LoadFrom_System_String_
After that, you can instantiate an implemenation of the interface you expect using reflection:
https://stackoverflow.com/a/26750/2396264
So the general idea is:
Let's say, that you provide this public interface and addon developers have classes that implement it:
public interface IMyAppAddon {
void Run();
}
Here's the general snippet on how you would achieve this (you will probably have to change something, but the idea should stay the same).
var appdataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var addonFolder = Path.Combine(appdataFolder, "myapp", "addons");
// List all DLL's under %appdata%
foreach (var dllFile in Directory.EnumerateFiles(addonFolder, "*.dll", SearchOption.AllDirectories) {
// Load the assembly
var assembly = Assembly.LoadFrom(dllFile);
// Get the implementations of your addon interface
var addonTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IMyAppAddon ).IsAssignableFrom(p));
// Instantiate the addon classes - note, this requires parameterless constructor on the addon class.
foreach (var addonType in addonTypes) {
var addonInstance = (IMyAppAddon)Activator.CreateInstance(addonType);
// Run each addon
addonInstance.Run();
}
}