Eklentileri yüklemek için özel bir AssemblyLoadContext'in nasıl oluşturulacağını gösteren ufak bir projedir. Eklentinin bağımlılıklarını çözmek için bir AssemblyDependencyResolver kullanılır. Eklentinin bağımlılıklarını barındırma uygulamasından doğru şekilde izole eder.
Göz attığım microsoft dökümanı
Ana projede (AppWithPlugin) eklenmiş olan eklenti projeleri (HelloPlugin ve GithubPlugin) bağımlılık olarak eklemeden çalışmasını sağlayan bir çözüm oluşturun. Bu, ana proje ile eklenti projeleri arasındaki bağımlılığı ortadan kaldırarak projeler arası esneklik ve bağımsızlık kazandırır.
Aynı çözüm altında oluşan farklı projeler olarak düşündüğüm için çözümün path'ini kök dizin
string root
olarak aldım.
static Assembly LoadPlugin(string relativePath)
{
string root = Path.GetFullPath(Path.Combine(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(
Path.GetDirectoryName(typeof(Program).Assembly.Location)))))));
string pluginLocation = Path.GetFullPath(Path.Combine(root, relativePath.Replace('\\', Path.DirectorySeparatorChar)));
PluginLoadContext loadContext = new PluginLoadContext(pluginLocation);
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
}
ICommand
interface'inden türeyen sınıfları bulur.
static IEnumerable<ICommand> CreateCommands(Assembly assembly)
{
int count = 0;
foreach (Type type in assembly.GetTypes())
{
if (typeof(ICommand).IsAssignableFrom(type))
{
ICommand result = Activator.CreateInstance(type) as ICommand;
if (result != null)
{
count++;
yield return result;
}
}
}
if (count == 0)
{
string availableTypes = string.Join(",", assembly.GetTypes().Select(t => t.FullName));
throw new ApplicationException(
$"Can't find any type which implements ICommand in {assembly} from {assembly.Location}.\n" +
$"Available types: {availableTypes}");
}
}
Important
Plugin olarak hazırlanan projelerde csproj dosyasında düzenlemeler yapılmalıdır.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PluginBase\PluginBase.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>
- EnableDynamicLoading → Projeyi eklenti olarak kullanılabilecek şekilde hazırlar . Diğer şeylerin yanı sıra bu, tüm bağımlılıklarını projenin çıktısına kopyalayacaktır.
- Private → Önemlidir. Bu, MSBuild'e PluginBase.dll dosyasını HelloPlugin'in çıkış dizinine kopyalamamasını söyler.
- ExcludeAssets → Önemlidir. PluginBaseBu ayar aynı etkiye sahiptir ancak projenin veya bağımlılıklarından birinin içerebileceği falsepaket referansları üzerinde çalışır.
- Pluginler eklenir. (Pathleri verilerek eklenir.)
- Listelemede eklenen pluginler gözükür. (Pluginin
Name
veMessage
alanları gözükür.) - Çalıştırmak istediğimizde pluginin
Execute
metodu çalışır.
HelloPlugin\bin\Debug\net8.0\HelloPlugin.dll
GithubPlugin\bin\Debug\net8.0\GithubPlugin.dll