Я создаю модульное приложение WPF с использованием библиотек Prism + Unity. Я разделил свои решения на следующие проекты:
- общий проект (интерфейсы)
- главное приложение, которое загружает dll
- модули, на которые НЕ ссылаются основные проекты приложений.
Подмодули dll собраны в папку bin \ (Debug | Release) \ Modules
Код в главном приложении для загрузки следующий:
Она:
- загружает dll из папки Modules
- типы регистров в контейнере DI
установка модулей из загруженного dll (поиск типов IModule)
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
base.ConfigureModuleCatalog(moduleCatalog);
List<Assembly> allAssemblies = new List<Assembly>();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (string dll in Directory.GetFiles(path + "/Modules/", "*.dll"))
allAssemblies.Add(Assembly.LoadFile(dll));
AutoRegisterClasses(allAssemblies);
var modules = AllClasses.FromAssemblies(allAssemblies).Where(t => t.GetInterfaces().Contains(typeof(IModule)));
foreach (var module in modules)
{
moduleCatalog.AddModule(
new ModuleInfo()
{
ModuleName = module.Name,
ModuleType = module.AssemblyQualifiedName,
Ref = "file://" + module.Assembly.Location
});
}
}
private void AutoRegisterClasses(List<Assembly> allAssemblies)
{
var defaultRegisters = AllClasses.FromAssemblies(allAssemblies).Where(t => t.IsDefined(typeof(AutoRegisterAttribute), true));
foreach (var register in defaultRegisters)
foreach (var interface_ in register.GetInterfaces())
Container.GetContainer().RegisterType(interface_, register, null, new TransientLifetimeManager());
}
Регистрация и инициализация модуля работает - все называется. Когда я пытаюсь разрешить взаимодействие из общего проекта , который реализован в проекте подмодуля , я получаю правильный объект. Но когда я пытаюсь отобразить ContentControl , который возвращается этим провайдером, я получаю следующее исключение:
Компонент «AdditionalDll.MainWindow» не имеет ресурса, идентифицируемого по URI '/AdditionalDll;component/mainwindow.xaml'.
Понятия не имею, почему это проблема, что более интересно, когда я не храню DLL в папке Modules - то есть, когда я храню их рядом с main exe, все работает !!!
Я создал минимальное решение, которое имеет эту проблему:
https://github.com/BAndysc/AssemblyLoadProblemExample
Common/Interfaces.cs - is common project, contains AutoRegister attribute and example interface that I will try to resolve
AdditionalDll/ExampleProvider.cs - is in submodule project, it is implementation of the mentioned interface, it returns new view from AdditionalDll project
TestMultiProjectApp/App.xaml.cs - setups everything - load dlls, register types, init modules
TestMultiProjectApp/MainWindow.xaml - is simple view, which shows given ContentControl
TestMultiProjectApp/MainWindowViewModel.cs - is simple viewmodel, which resolves IProvider interface (it works) and on command assigns returned view to property, which is then displayed by view (this causes exception)
Несмотря на то, что хранить dll в той же папке, что и exe, - это обходной путь, я бы предпочел хранить их в отдельной папке, чтобы сохранить порядок, если у кого-то есть идеи, как их исправить, я буду признателен за это.