複数のdllからmethod injectionしたい
解決したいこと
実行ディレクトリの下のpluginsディレクトリの中に、複数のdllが入っています。
これらのdllにはIDropPluginインターフェースを実装したクラスとIModuleインターフェースを実装したクラスが含まれています。
IDropPluginインターフェース
using System.Windows;
namespace Sunctum.Plugin
{
public interface IDropPlugin
{
string AcceptableDataFormat { get; }
void Execute(IDataObject dataObject);
}
}
プラグイン1(インポート機能を実装)
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using Sunctum.Plugin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FolderFilesImporter
{
public class FolderFilesImporterModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IDropPlugin, FolderFilesImporter>();
}
}
}
using NLog;
using Sunctum.Domain.Logic.Async;
using Sunctum.Domain.Models;
using Sunctum.Domain.Models.Managers;
using Sunctum.Plugin;
using System;
using System.Windows;
using Unity;
namespace FolderFilesImporter
{
public class FolderFilesImporter : IDropPlugin
{
private static readonly Logger s_logger = LogManager.GetCurrentClassLogger();
public string AcceptableDataFormat => DataFormats.FileDrop;
[Dependency]
public IBookImporting BookImportingService { get; set; }
[Dependency]
public ITaskManager TaskManager { get; set; }
public async void Execute(IDataObject dataObject)
{
if (dataObject.GetData(DataFormats.FileDrop) is string[] objects && objects.Length > 0)
{
try
{
BookImportingService.MasterDirectory = Specifications.MASTER_DIRECTORY;
BookImportingService.ObjectPaths = objects;
await TaskManager.Enqueue(BookImportingService.GetTaskSequence());
}
catch (NullReferenceException e)
{
s_logger.Error(e, "Failed to import.");
}
catch (Exception e)
{
s_logger.Error(e, "Failed to import.");
}
}
}
}
}
プラグイン2(ダミー)
using Prism.Ioc;
using Prism.Modularity;
using Sunctum.Plugin;
using System;
namespace WpfLibrary1
{
public class Class1 : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IDropPlugin, Class2>();
}
}
}
using Sunctum.Plugin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfLibrary1
{
public class Class2 : IDropPlugin
{
public string AcceptableDataFormat => string.Empty;
public void Execute(IDataObject dataObject)
{
}
}
}
dllを読み込むアプリ側の実装
using Homura.Core;
using NLog;
using Prism.Commands;
using Prism.Regions;
using Prism.Services.Dialogs;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using Sunctum.Converters;
using Sunctum.Core.Extensions;
using Sunctum.Domain.Extensions;
using Sunctum.Domain.Logic.DisplayType;
using Sunctum.Domain.Logic.Load;
using Sunctum.Domain.Logic.Query;
using Sunctum.Domain.Models;
using Sunctum.Domain.Models.Managers;
using Sunctum.Domain.ViewModels;
using Sunctum.Plugin;
using Sunctum.UI.Controls;
using Sunctum.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Unity;
namespace Sunctum.ViewModels
{
public abstract class DocumentViewModelBase : DockElementViewModelBase, IDocumentViewModelBase, IDisposable
{
:
[Dependency]
public ISelectManager SelectManager { get; set; }
[Dependency]
public Lazy<ILibrary> LibraryManager { get; set; }
[Dependency]
public Lazy<IMainWindowViewModel> MainWindowViewModel { get; set; }
:
#region プロパティ
[Dependency]
public IEnumerable<Lazy<IDropPlugin>> DropPlugins { get; set; }
public DocumentViewModelBase(IDialogService dialogService)
{
RegisterCommands();
:
}
private void RegisterCommands()
{
:
DropCommand.Subscribe(args =>
{
foreach (var dropPlugin in DropPlugins)
{
dropPlugin.Value.Execute(args.Data);
}
})
.AddTo(disposables);
:
}
}
}
私が実現したいことは、「pluginsディレクトリに入っているIDropPluginインターフェースを実装した複数のdllを読み込んで、DropCommandが発火したらそれら全てのdllの機能を実行したい」のですが、
[Dependency]
public IEnumerable<Lazy<IDropPlugin>> DropPlugins { get; set; }
上記のIEnumerable>の書き方がまずいのか、それともIContainerRegistry.Resigter()を2回実行しているのがまずいのか、一つのdllしかインジェクトされません。(この場合、WpfLibrary1(ダミーの方)がインジェクトされる)
一つのインターフェースを実装した複数のDLLをロードしてメソッドをインジェクトするいいアイディアはないでしょうか?
該当するソースコード
ブランチ:feature/multiple-dll-injection
自分で試したこと
IEnumerable>ではダメでした。これがダメというより、IContainerRegistry.Register()を2回実行していると、最初に実行した方が上書きされてしまっているような気がします。