2013-03-14 2 views
0

Я пишу архитектуру плагина для планировщика автоматизации, который должен быть надежным, поэтому я пытаюсь выполнить ASP.NET/IIS-стиль AppDomains - то есть каждый AppDomain является действительно рассматривается как свое собственное приложение без общих объектов между ними.Полная изоляция сборки AppDomain в ASP.NET

Я устанавливаю ApplicationBase, ConfigurationFile и ShadowCopyFiles в AppDomainSetup.

В планировщике автоматизации есть одна общая сборка, которую я загружаю для каждого плагина - он обрабатывает основную сборку плагина, захватывает неперехваченные исключения и регистрирует. Есть несколько недостатков этого подхода, который я идентифицировал:

  • Устанавливая ApplicationBase где плагин хранится, все зависимости от общей сборки (который находится в другом пути) не будет больше не решены , Я как-то взломал это на работу, подключив событие AssemblyResolve, но это приводит к другим проблемам.

  • Возможно, что как общая сборка, так и плагин ссылаются на свои собственные копии одноименной сборки - возможно, каждая из них имеет другую версию. Или, может быть, сборка с тем же именем, но совершенно другое содержимое. Переопределяя AssemblyResolve, копия плагина всегда будет загружена первой.

  • Не очень беспокоиться об этом, но с точки зрения безопасности. Я понимаю, что плагин может переопределить зависимость планировщика, заставляя его делать что-то нехорошее или отражать общую сборку и получать внутренности.

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

Как вы думаете?

ответ

0

Я не уверен, что это точно отвечает на ваш вопрос, но у нас была аналогичная настройка с приложением, в котором у нас были независимые дочерние AppDomains и папка с общими библиотеками DLL, и у нас был успех без использования AssemblyResolve.

Наша структура файла был:

[PathToApplication]\OurApplication.exe 
[PathToApplication]\AddIns\[SharedAssemblies]\*.dll 
[PathToApplication]\AddIns\[FirstAddIn]\*.dll 
[PathToApplication]\AddIns\[SecondAddIn]\*.dll 

Где части в квадратных скобках заменены реальными путями.

В нашем случае общие сборки, которые также загружаются основным AppDomain, поэтому мы установили это в главном App.config следующим образом.

<runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
    <probing privatePath="AddIns\[SharedAssemblies]" /> 
    </assemblyBinding> 
</runtime> 

Убедитесь, что общие собрания не существуют наряду с основным исполняемым файлом или она будет загружать их оттуда вместо этого, и что молча остановит библиотеку DLL, разделяемым в памяти между всем AppDomains.

Затем для каждого AppDomain надстройки мы сконфигурировали его так, чтобы базовый путь был папкой, расположенной как над папкой надстройки, так и с общей папкой, и установил пути для личных bin, чтобы он искал правильные подпапки в правильный порядок:

var basePath = @"[PathToApplication]\AddIns"; 

var configFile = Path.Combine(
     basePath, 
     addInFolder, 
     addInAssemblyName + ".dll.config"); 

var binPaths = new [] { "[SharedAssemblyFolder]", addInFolder }; 

setup = new AppDomainSetup 
{ 
    ApplicationBase = basePath, 
    ConfigurationFile = configFile, 
    LoaderOptimization = LoaderOptimization.MultiDomain, 
    PrivateBinPath = string.Join(";", binPaths), 
    PrivateBinPathProbe = string.Empty, 
}; 

таким образом, он всегда ищет общую папку первую, так что даже если надстройка предоставляет свой собственный DLL с тем же именем, то он будет проигнорирован.

Мы запускаем это с [System.LoaderOptimization(LoaderOptimization.MultiDomain)], установленным в точке входа приложения, и проверили, что библиотеки DLL фактически разделены в памяти (легко получить это немного неправильно и молча остановить это).

Надеюсь, это поможет в некотором роде.

Смежные вопросы