Создаю новый домер через AppDomain.CreateDomain(), но потом, при вызове CreateInstanceAndUnwrap(), для поиска сборки должно вызваться событие AssemblyResolve созданного домена, но не вызывается, в чем может быть проблема?
Код:
AppDomain domain = AppDomain.CreateDomain("ClientDomain");
domain.AssemblyResolve += new ResolveEventHandler(domain_AssemblyResolve);
domain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
{ // сюда не заходитif(File.Exists(_deployPath + args.Name))
return Assembly.Load(_deployPath + args.Name);
return null;
};
Form form = (Form)domain.CreateInstanceAndUnwrap("AssemblyName", "Type"); // тут падает
Эксепшен:
Could not load file or assembly 'AssemblyName' or one of its dependencies.
An error relating to serialization occurred. (Exception from HRESULT: 0x8013150C)
Re: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 09:58
Оценка:
Здравствуйте, Chardex, Вы писали:
C>Создаю новый домер через AppDomain.CreateDomain(), но потом, при вызове CreateInstanceAndUnwrap(), для поиска сборки должно вызваться событие AssemblyResolve созданного домена, но не вызывается, в чем может быть проблема?
1. Подозреваю, что сборка всё же находиться, и исключение не связанно с отсутствием сборки. Вероятно исключение происходит как раз во время создания объекта (например, в конструкторе).
2. Попробуй использовать не анонимный делегат, а обычный, как в .NET 1.1
3. Кстати, тот код, которым ты в делегате загружаешь сборку, — никогда ничего не загрузит.
Здравствуйте, Аноним, Вы писали:
А>1. Подозреваю, что сборка всё же находиться, и исключение не связанно с отсутствием сборки. Вероятно исключение происходит как раз во время создания объекта (например, в конструкторе).
Конструктор — пустой, просто форма, создання студий по умолчанию.
InnerException полученного Exception вот какой:
"Type 'System.ResolveEventArgs' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable."
Может из-за этого?
А>2. Попробуй использовать не анонимный делегат, а обычный, как в .NET 1.1
Пробовал. Тоже самое
А>3. Кстати, тот код, которым ты в делегате загружаешь сборку, — никогда ничего не загрузит.
Это почему?
Разобрался, оказывается подписчик события AssemblyResolve должен быть в том же домене, иначе получается, что при вызове метода за пределами домена параметры метода будут сериализовываться, а ResolveEventArgs не помечени как Serializable. Я правильно рассуждаю...?
Re[5]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 11:45
Оценка:
Здравствуйте, Chardex, Вы писали:
C>Разобрался, оказывается подписчик события AssemblyResolve должен быть в том же домене, иначе получается, что при вызове метода за пределами домена параметры метода будут сериализовываться, а ResolveEventArgs не помечени как Serializable. Я правильно рассуждаю...?
Да, правильно. И как я сразу не сообразил
Re[3]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 11:51
Оценка:
Здравствуйте, Chardex, Вы писали:
А>>3. Кстати, тот код, которым ты в делегате загружаешь сборку, — никогда ничего не загрузит. C>Это почему?
Потому что:
1. _deployPath у тебя оканчивается символом '\\' или нет? Если нет — ошибка.
2. допустим у тебя в _deployPath путь типа "C:\\Deploy Path\\", а имя сборки, которую мы ищем, — "yourasm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", тогда после твоего оператора сложения будет
Здравствуйте, Аноним, Вы писали:
А>Да, правильно. И как я сразу не сообразил
Вкратце: есть главная форма, в ней создаю новый AppDomain, в нем показываю другую форму. При закрытии второй формы, выгружаю созданный домен, выгрузку делаю в методе первой формы, но почему-то после вызова AppDomain.Unload(_domain) сразу диспозится первая форма (прям сразу после вызова отладчик переходит внутрь Dispose() первой формы) и все приложение завершается.
Re[7]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 12:20
Оценка:
Здравствуйте, Chardex, Вы писали:
C>Здравствуйте, Аноним, Вы писали:
А>>Да, правильно. И как я сразу не сообразил C>Вкратце: есть главная форма, в ней создаю новый AppDomain, в нем показываю другую форму. При закрытии второй формы, выгружаю созданный домен, выгрузку делаю в методе первой формы, но почему-то после вызова AppDomain.Unload(_domain) сразу диспозится первая форма (прям сразу после вызова отладчик переходит внутрь Dispose() первой формы) и все приложение завершается.
Хм... Это странно. А вы уверены в том, что показываете форму в другом, созданном AppDomain'е, а не в первом? Мне кажется, что в первом.
Приведите код, как создаёте домен, как сохраняете новый объект AppDomain, как показываете форму в нём и как выгружаете его.
Здравствуйте, Аноним, Вы писали:
А>Хм... Это странно. А вы уверены в том, что показываете форму в другом, созданном AppDomain'е, а не в первом? Мне кажется, что в первом. А>Приведите код, как создаёте домен, как сохраняете новый объект AppDomain, как показываете форму в нём и как выгружаете его.
В главной форме:
private void CreateDomain()
{
AppDomain domain = AppDomain.CreateDomain("ClientDomain");
AssemblyResolveFinder finder = (AssemblyResolveFinder)domain.CreateInstanceAndUnwrap(typeof(AssemblyResolveFinder).Assembly.FullName, typeof(AssemblyResolveFinder).FullName);
finder.DeployPath = _deployPath;
domain.AssemblyResolve += new ResolveEventHandler(finder.AssemblyResolve);
Hide();
DomainConnector connector = new DomainConnector(_connection);
domain.SetData(DomainConnector.ObjectName, connector);
domain.CreateInstance("...", "...");
connector.Terminated +=new TerminateDelegate(DomainConnectorTerminated);
}
private void DomainConnectorTerminated(bool close)
{
if (close)
Close();
else
Show();
}
public class AssemblyResolveFinder : MarshalByRefObject
{
private string _deployPath;
public Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
string path = _deployPath + args.Name + ".dll";
if (File.Exists(path))
return Assembly.LoadFrom(path);
return null;
}
public string DeployPath
{
get { return _deployPath; }
set { _deployPath = value; }
}
}
public delegate void TerminateDelegate(bool close);
public sealed class DomainConnector : MarshalByRefObject
{
public const string ObjectName = "Connector";
public DomainConnector(IUniversalConnection connection)
{
_connection = connection;
}
IUniversalConnection _connection;
public event TerminateDelegate Terminated;
public IUniversalConnection Connection
{
get { return _connection; }
}
public void Terminate(bool close)
{
if (Terminated != null)
Terminated(close);
}
}
Re[9]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 13:14
Оценка:
Так всё правильно, у тебя же в первой (главной) форме вызывается Close()! Вот она и закрывается.
1. У тебя сначала закрывается вторая форма (MainForm). И ещё до выгрузки созданного домена у тебя происходит следующее:
2. В обработчике события Closed вызывается connector.Terminate
3. В методе DomainConnector.Terminate() вызывается событие Terminated
4. На событие Terminated у тебя подписан кто? Правильно, первая форма! Обработчик называется DomainConnectorTerminated, вот он и закрывает (диспозит) первую форму.
Здравствуйте, Аноним, Вы писали:
А>Так всё правильно, у тебя же в первой (главной) форме вызывается Close()! Вот она и закрывается.
Если я жму на кнопочку button1, то вместо Close() вызывается Show();
А>1. У тебя сначала закрывается вторая форма (MainForm). И ещё до выгрузки созданного домена у тебя происходит следующее: А>2. В обработчике события Closed вызывается connector.Terminate А>3. В методе DomainConnector.Terminate() вызывается событие Terminated А>4. На событие Terminated у тебя подписан кто? Правильно, первая форма! Обработчик называется DomainConnectorTerminated, вот он и закрывает (диспозит) первую форму.
Спасибо что объяснили как работает мой код
Re[11]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 15:59
Оценка:
Здравствуйте, Chardex, Вы писали:
А>>1. У тебя сначала закрывается вторая форма (MainForm). И ещё до выгрузки созданного домена у тебя происходит следующее: А>>2. В обработчике события Closed вызывается connector.Terminate А>>3. В методе DomainConnector.Terminate() вызывается событие Terminated А>>4. На событие Terminated у тебя подписан кто? Правильно, первая форма! Обработчик называется DomainConnectorTerminated, вот он и закрывает (диспозит) первую форму. C>Спасибо что объяснили как работает мой код
Здравствуйте, Аноним, Вы писали: C>>Спасибо что объяснили как работает мой код А>Обращайся ещё
Это же шутка была... я сам писал код и понимаю как он работает. Проблема все еще не решена
Re[13]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 16:45
Оценка:
Здравствуйте, Chardex, Вы писали:
C>Здравствуйте, Аноним, Вы писали: C>>>Спасибо что объяснили как работает мой код А>>Обращайся ещё C>Это же шутка была... я сам писал код и понимаю как он работает. Проблема все еще не решена
Так а в чём проблема? Код верный. Как он работает, вы знаете. Почему вызывается Dispose() первой формы, я вам объяснил.
C>Если я жму на кнопочку button1, то вместо Close() вызывается Show();
Ну а когда вы жмёте крестик в окне второй формы (MainForm), вызывается Close().
P.S. Кстати, вы говорили, что AppDomain.Unload() вызываете из первой формы, но по коду получается, что из второй (MainForm).
Здравствуйте, Аноним, Вы писали:
А>Так а в чём проблема? Код верный. Как он работает, вы знаете. Почему вызывается Dispose() первой формы, я вам объяснил.
В том что когда жму на кнопочку, для первой формы делается Show а не Close, но Dispose все равно происходит.
C>>Если я жму на кнопочку button1, то вместо Close() вызывается Show();
А>Ну а когда вы жмёте крестик в окне второй формы (MainForm), вызывается Close().
А>P.S. Кстати, вы говорили, что AppDomain.Unload() вызываете из первой формы, но по коду получается, что из второй (MainForm).
Это была старая версия
Re[15]: AppDomain и AssemblyResolve
От:
Аноним
Дата:
24.09.06 19:42
Оценка:
Здравствуйте, Chardex, Вы писали:
C>Здравствуйте, Аноним, Вы писали:
А>>Так а в чём проблема? Код верный. Как он работает, вы знаете. Почему вызывается Dispose() первой формы, я вам объяснил. C>В том что когда жму на кнопочку, для первой формы делается Show а не Close, но Dispose все равно происходит.
C>>>Если я жму на кнопочку button1, то вместо Close() вызывается Show();