Как сделать провайдер настроек внутри динамически загруженной сборки доступным для размышления?

После этого вопроса я успешно создал своего провайдера пользовательских настроек в устаревшем приложении C#, которое мы разрабатываем. На него ссылаются через SettingsProvider атрибут:

public sealed class MySettings : SettingsProvider
{
    ...
}

[SettingsProvider(typeof(MySettings))]
internal sealed partial class Settings {}

Однако теперь я столкнулся с другой проблемой.

Наше клиентское приложение включает в себя средство автообновления, и оно реализовано таким образом, что основная часть клиента, включая вышеупомянутые классы, встроена в DLL (назовем ее здесь client.dll), которая затем используется EXE- файлом. Сначала EXE проверяет наличие обновлений и при необходимости загружает последнюю версию с сервера обновлений, заменяя все библиотеки DLL и т. Д. Их более новой версией (включая client.dll). Чтобы иметь возможность заменять библиотеки DLL во время выполнения, они не могут ссылаться на них статически. Поэтому после обновления он загружает client.dll и запускает его так:

Assembly assy = Assembly.LoadFile(
        AppDomain.CurrentDomain.BaseDirectory + "client.dll");
object frm = assy.CreateInstance("Client.Forms.MainForm");
Application.Run((Form)frm);

Печальным последствием этого является то, что фреймворк не может найти мой класс провайдера пользовательских настроек внутри динамически загружаемой сборки. Я пытался использовать LoadFrom вместо LoadFile выше, но это не помогло. Единственное работающее решение, которое я нашел до сих пор, - это реализовать прокси-класс в exe-загрузчике с тем же именем, что и у реального провайдера настроек, который полностью найден платформой. Затем прокси-сервер создает экземпляр реального поставщика настроек из клиентской сборки и делегирует ему все вызовы.

Кажется, это работает, но я не доволен этим. Есть ли способ помочь каркасу найти мой класс внутри динамически загружаемой сборки?

Обновить

Сообщение об ошибке я получаю:

System.Configuration.ConfigurationErrorsException: Failed to load provider type: Client.Properties.MySettings, Client, Version=4.0.1341.0, Culture=neutral, PublicKeyToken=null.
   at System.Configuration.ApplicationSettingsBase.get_Initializer()
   at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propInfo)
   at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
   at System.Configuration.ApplicationSettingsBase.get_Properties()
   at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
   at System.Configuration.SettingsBase.get_Item(String propertyName)
   at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
   at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
   at Client.Properties.Settings.get_SomeConfigSetting()
   at ...

Посредством сообщений отладки и регистрации я определил, что метод инициализатора класса никогда не вызывается, поэтому класс никогда не создается. Другими словами, похоже, что за вышеприведенным исключением нет скрытой ошибки инициализации.

Еще один потенциально важный момент: клиент в настоящее время работает на.NET 2.0, и в обозримом будущем не планируется его обновление.

Обновление 2

Я начал исследовать AppDomain, как подсказал ответ @jwddixon. Сначала я хотел проверить, действительно ли Client.dll оказывается в другом домене приложения, чем домен вызывающего EXE-файла. Таким образом, я перечислил сборки в текущем домене приложения и увидел, что Клиент на самом деле там. Но, к моему удивлению, я заметил, что на самом деле в списке есть две сборки с именем Client - и EXE, и DLL имеют одно и то же имя сборки, но разную версию (4.0.0.0 для EXE, 4.0.1352.0 для DLL в настоящее время).). До сих пор я не был полностью осведомлен об этом, и это может быть важно. Я постараюсь изменить имя сборки EXE дальше...

Обновление 3

... и это на самом деле решило проблему! Ааааа... По отношению к моим неизвестным предшественникам, которые изобрели эту искаженную схему, для тех, кто знает почему, у меня очень странные мысли в данный момент... но спасибо всем вам, ребята, за то, что они внесли вопросы и идеи, которые в конечном итоге приводят к решению!

1 ответ

Я не пробовал это, но как насчет чего-то вроде:

AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
AppDomain domain = AppDomain.CreateDomain("myAppDomain", null, setup)
setup.ApplicationBase = file;

Assembly assy = domain.Load(AssemblyName.GetAssemblyName(
AppDomain.CurrentDomain.BaseDirectory +
 "client.dll"));

object frm = assy.CreateInstance("Client.Forms.MainForm");
Application.Run((Form)frm);
Другие вопросы по тегам