Требуется помощь для выгрузки .DLL из AppDomain - все еще не работает даже с ShadowCopy - PullRequest
3 голосов
/ 18 февраля 2011

Я пытаюсь сделать следующее. Приложение А - это «приложение для мамы». Он остается открытым. Приложение B - это просто .DLL, где я пишу некоторые классы, производные от интерфейса, указанного в приложении A.

Затем из приложения A я «импортирую» классы из приложения B и запускаю в них методы. Я хочу иметь возможность динамически изменять приложение B (изменить код и перекомпилировать) и использовать новый код в приложении A.

У меня есть команда посткомпиляции в приложении B, которая копирует новый .DLL в каталог приложения A. Приложение A создает новый домен приложений и использует ShadowCopying. Я подумал, что этого будет достаточно, но когда я пытаюсь перекомпилировать и скопировать новый .DLL приложения B, он говорит, что файл используется и не может быть перезаписан.

Вот код, который у меня есть на данный момент:

Приложение A (TestServer в коде):

namespace TestServer
{
    public interface IRunnable
    {
        void Run();        
    }

    class Program
    {        
        static void Main(string[] args)
        {
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationName = "DemoApp";
            setup.ApplicationBase = Environment.CurrentDirectory;
            setup.ShadowCopyDirectories = Environment.CurrentDirectory;
            setup.ShadowCopyFiles = "true";
            int _domain = 1;

            while (true)
            {
                string typeName = Console.ReadLine();

            AppDomain appDomain = AppDomain.CreateDomain("DemoDomain" + _domain, null, setup);

            IRunnable runner = appDomain.CreateInstanceFromAndUnwrap("TestClient.dll", typeName) as IRunnable;

            runner.Run();

            AppDomain.Unload(appDomain);
            _domain++;
            }
        }   
    }   
}

Приложение B (TestClient в коде):

namespace TestClient
{    
    public class TestRunner : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("RUNNING");
        }
    }

    public class Bob : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("BOB");
        }
    }
}

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

Как я могу решить эту проблему / есть ли лучшая настройка ??

ПРИМЕЧАНИЕ. Я обновил свой код, и он все еще дает тот же результат.

Ответы [ 3 ]

3 голосов
/ 18 февраля 2011

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

Я не уверен на 100%, но это, безусловно, один шаг, который вам придется сделать

Обновление

С точки зрения решения, представленного там, создание экземпляра бегуна происходит в наследнике DomainLifetimeHook. Показанная инфраструктура обеспечивает запуск методов Start и Stop в AppDomain, созданном классом AppDomainExpander. Этот Expander является классом, который создает новый домен, поэтому настройка вашего домена должна идти в методе Create домена.

0 голосов
/ 18 февраля 2011

Тип должен быть загружен в основной домен приложения, как только вы развернете ObjectHandle.Для правильной работы вам нужно работать с неразвернутым ObjectHandle.

0 голосов
/ 18 февраля 2011

Основная проблема в том, где вы делаете:

Type type = assm.GetType("TestClient." + typeName);

Это происходит в главном AppDomain приложения A, и в результате основной домен AppDomain блокирует сборку приложения B. DLL

Ссылка в ответе flq на его пост в блоге должна работать для вас.

...