У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция
double f(double[] args)
{
return 2*args[0];
}
и в процессе работы программы мне нужно её заменить на такую же, только выполняющую
return args[0]+5;
Как такое можно сделать? Пробовал приводить класс к типу TypeBuilder и потом определять в нем метод — получается ерунда.
З.Ы.: Пытался искать книги специально по Reflection.Emit — не нашел, везде на него больше пары глав не выделяется.... Может кто знает хорошую книжку по нему? MSDN конечно вещь хорошая, но с книжкой, тем более на русском, было бы гораздо удобнее....
Re: книга по Reflection.Emit и модификация классов на лету
Здравствуйте, 4D man, Вы писали:
4M>У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция
Типы с помощью Reflection метять (добавлять/удалять/подменять методы/поля) нельзя. Можно только создавать новые типы. При желании наследоваться от старых
ICQ: 446240
Re[2]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Miem, Вы писали:
M>Здравствуйте, 4D man, Вы писали:
4M>>У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция
M>Типы с помощью Reflection метять (добавлять/удалять/подменять методы/поля) нельзя. Можно только создавать новые типы. При желании наследоваться от старых
Тогда напрашивается вообще глупый вопрос: а вообще это можно как-то сделать, т.е. сделать так, чтобы класс динамически менялся.
Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
Re: книга по Reflection.Emit и модификация классов на лету
Здравствуйте, 4D man, Вы писали:
4M>У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция 4M>double f(double[] args) 4M>{ 4M> return 2*args[0]; 4M>} 4M>и в процессе работы программы мне нужно её заменить на такую же, только выполняющую 4M> return args[0]+5; 4M>Как такое можно сделать? Пробовал приводить класс к типу TypeBuilder и потом определять в нем метод — получается ерунда.
Интерфейс класса должен менятся или нет? Или должна менятся только его реализация?
Re[3]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, 4D man, Вы писали:
4M>Здравствуйте, Miem, Вы писали:
M>>Здравствуйте, 4D man, Вы писали:
4M>>>У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция
M>>Типы с помощью Reflection метять (добавлять/удалять/подменять методы/поля) нельзя. Можно только создавать новые типы. При желании наследоваться от старых 4M>Тогда напрашивается вообще глупый вопрос: а вообще это можно как-то сделать, т.е. сделать так, чтобы класс динамически менялся. 4M>Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
А почему ты не хочешь сделать по другому? ЧТо бы класс не менялся, но он вызывал другой класс, который рулил бы какой класс ему возвращять ? НА мой взгляд здесь фабрика классов рулит по полной программе.
Да пребудет с тобой Великий Джа
Re[4]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Miem, Вы писали:
M>Здравствуйте, 4D man, Вы писали:
4M>>Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
M>ничего, ну разве что отнаследоваться от него и перегрузить методы
Я пробовал так делать. Только вот класс меняется достаточно часто, поэтому появляются многочисленные наследования, зачастую меняющие лишь один член класса. В итоге произоводительность сильно падает...
Re[2]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, 4D man, Вы писали:
4M>>У меня возникла такая проблема: существует класс, который в процессе работы программы должен постоянно модифицироваться: функции должны заменяться, удаляться и создаваться. Т.е. допустим у меня в этом классе есть функция 4M>>double f(double[] args) 4M>>{ 4M>> return 2*args[0]; 4M>>} 4M>>и в процессе работы программы мне нужно её заменить на такую же, только выполняющую 4M>> return args[0]+5; 4M>>Как такое можно сделать? Пробовал приводить класс к типу TypeBuilder и потом определять в нем метод — получается ерунда.
L>Интерфейс класса должен менятся или нет? Или должна менятся только его реализация?
В классе всегда одна функция, у неё меняется только реализация, и ещё постоянно добавляются/убираются/модифицируются однотипнюе функции типа
double _имя функции_(double[] args)
У них меняются только название и код, которые вводятся пользователем.
Вот, собственно, и весь интерфейс класса.
Re[3]: книга по Reflection.Emit и модификация классов на лет
— собираешь код просто как текст в один файл .cs
— компилишь его
— загружаешь ассемблю в отдельный домен
— юзаешь ее
— выгружаешь
делаешь все снова
главное минимизировать междоменный обмен данными, чтобы как можно меньше тормозило
т.е. придется основной алгоритм, который юзает ту функцию, вынести в отдельную ассемблю и загружать ее в том же отдельном домене
Re[4]: книга по Reflection.Emit и модификация классов на лет
4M>Тогда напрашивается вообще глупый вопрос: а вообще это можно как-то сделать, т.е. сделать так, чтобы класс динамически менялся. 4M>Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
Посмотри System.Reflection.Emit.MethodRental. Кажется, это то, что тебе нужно.
... << RSDN@Home 1.0 beta 7a >>
Re[5]: книга по Reflection.Emit и модификация классов на лет
M>Фигня. Тормозить будет компиляция C#. Там при каждой компиляции запускается отдельный процесс csc.exe, куда там междоменному обмену до таких тормозов!
я думал один раз скомпилить код, потом юзать его долго в каком то страшном алгоритме
Re[6]: книга по Reflection.Emit и модификация классов на лет
M>Фигня. Тормозить будет компиляция C#. Там при каждой компиляции запускается отдельный процесс csc.exe, куда там междоменному обмену до таких тормозов!
B>я думал один раз скомпилить код, потом юзать его долго в каком то страшном алгоритме
Тогда конечно. Но по сути задачи, вроде бы, код будет меняться нередко.
Кстати, грузить скомпилированную сборку вполне можно и прямо в текущий домен.
... << RSDN@Home 1.0 beta 7a >>
Re[7]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Banch, Вы писали:
M>>Кстати, грузить скомпилированную сборку вполне можно и прямо в текущий домен.
B>да, но если грузить в отдельный то ее потом можно будет выгрузить
Экстремалы, блин Да у парня просто проблемы с архитектурой, а вы тут такие темы задвигаете . И правильно ему посоветовал Ведмедь про фабрику классов или еще там чего, но только не так...
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[4]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Ведмедь, Вы писали:
В>А почему ты не хочешь сделать по другому? ЧТо бы класс не менялся, но он вызывал другой класс, который рулил бы какой класс ему возвращять ? НА мой взгляд здесь фабрика классов рулит по полной программе.
Т.е.? В смысле "рулил бы какой класс ему возвращять"? Нельзя ли поподробнее? А то я не очень понял что Вы имеете ввиду.
Re[5]: книга по Reflection.Emit и модификация классов на лет
От:
Аноним
Дата:
18.06.03 09:34
Оценка:
Здравствуйте, 4D man, Вы писали:
4M>Здравствуйте, Miem, Вы писали:
M>>Здравствуйте, 4D man, Вы писали:
4M>>>Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
M>>ничего, ну разве что отнаследоваться от него и перегрузить методы 4M>Я пробовал так делать. Только вот класс меняется достаточно часто, поэтому появляются многочисленные наследования, зачастую меняющие лишь один член класса. В итоге произоводительность сильно падает...
а может здесь не фабрика нужна а декоратор ??
Re[5]: книга по Reflection.Emit и модификация классов на лет
4M>Т.е.? В смысле "рулил бы какой класс ему возвращять"? Нельзя ли поподробнее? А то я не очень понял что Вы имеете ввиду.
На первый взгляд видится так:
public abstract class Evalution
{
public abstract double Eval( double[] args );
}
public void InvokeEvalution
{
protected Evalution _evalution = null;
public double Invoke( double[] args )
{
if( _evalution == null )
throw new Exception("выражение не задано");
return _evalution.Eval( args );
}
public Evalution Eval
{
set
{
evalution = val;
}
}
}
А дальше соотвесвенно где-то в коде
{
InvokeEvalution invoke_evalution = new InvokeEvalution();
invoke_evalution.Eval = CreateEvalution( code_source );// Функция, которая создает класс производный от Evalution c переопреденным методом Eval, в котором реализован нужный код.for( int i = 0 ; i < 100000; i++ )
{
Console.WriteLine( "result = {0}",invoke_evalution.Invoke( 1.0, 2.1, 3.2 ) );
}
}
Я правильно понял это имелось ввиду?
Да пребудет с тобой Великий Джа
Re[6]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, Ведмедь, Вы писали:
В>Здравствуйте, 4D man, Вы писали:
4M>>Т.е.? В смысле "рулил бы какой класс ему возвращять"? Нельзя ли поподробнее? А то я не очень понял что Вы имеете ввиду.
В>На первый взгляд видится так:
<> В>Я правильно понял это имелось ввиду?
Почти. Спасибо за написаный код. Только вот помимо метода Eval
в class Evalution в нём(этом классе) будут ещё функции которые
мне нужно будет менять. Из кода же я понял, что Вы предлагаете
при каждом изменении набора функций заново создавать производный
от Evalution класс с перегруженными функциями. Я же имел ввиду
один раз создать тип класса, а потом только менять его содержимое.
Re[4]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, mihailik, Вы писали:
4M>>Тогда напрашивается вообще глупый вопрос: а вообще это можно как-то сделать, т.е. сделать так, чтобы класс динамически менялся. 4M>>Или, как я понял, после tb.CreateType(); с типом уже ничего не сделаешь?
M>Посмотри System.Reflection.Emit.MethodRental. Кажется, это то, что тебе нужно.
Посморел. Почти оно. Только вот как добавлять на ходу эти методы?
Я пробовал после CreateType вызывать DefineMethod — VS ругается,
пишет : Unable to change after type has been created.
Re[5]: книга по Reflection.Emit и модификация классов на лет
M>Посмотри System.Reflection.Emit.MethodRental. Кажется, это то, что тебе нужно.
4M>Посморел. Почти оно. Только вот как добавлять на ходу эти методы? 4M>Я пробовал после CreateType вызывать DefineMethod — VS ругается, 4M>пишет : Unable to change after type has been created.
Нет, добавлять на ходу нельзя. Только старые портить.
Как портить — там примерчик есть. Не очень удобно, честно говоря, но хоть как-то
... << RSDN@Home 1.0 beta 7a >>
Re[7]: книга по Reflection.Emit и модификация классов на лет
4M>Из кода же я понял, что Вы предлагаете 4M>при каждом изменении набора функций заново создавать производный 4M>от Evalution класс с перегруженными функциями. Я же имел ввиду 4M>один раз создать тип класса, а потом только менять его содержимое.
А нельзя сразу определить весь набор этих перегруженных функций?
... << RSDN@Home 1.0 beta 7a >>
Re[8]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, mihailik, Вы писали:
M>А нельзя сразу определить весь набор этих перегруженных функций?
??? В том-то и дело, что нет, т.к. во время работы программы набор функций постоянно меняется. Причем кол-во функций теоретически может быть вообще бесконечно большим, сколько в память влезет. Так что заранее сказать, какие там функции будут и сколько их, нельзя....
Re[9]: книга по Reflection.Emit и модификация классов на лет
Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k.
Re[10]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, 4D man, Вы писали:
4M>Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k.
Создавай новые класы в другом домене, как посчитаешь что нужно освободить память грохай домен, создавай новый и все заново
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[11]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, Miem, Вы писали:
M>Здравствуйте, 4D man, Вы писали:
4M>>Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k. M>Создавай новые класы в другом домене, как посчитаешь что нужно освободить память грохай домен, создавай новый и все заново
Понятнетько...
Тогда такой вопрос, возможно глупый, т.к. ещё не успел порыть MSDN по этой теме, — как узнать, сколько память отожрал этот домен, чтобы грохать его когда нужно, а не при каждом новом классе?
Re[12]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, Miem, Вы писали:
4M>>как узнать, сколько память отожрал этот домен, чтобы грохать его когда нужно, а не при каждом новом классе?
M>А я тоже не знаю. ИМХО никак. Просто ограничивай количество классов. Найди для себя приемлемое. M>А про память смотри Соседний топик
Ага, 1-2-3-4-5-казнить!-1-2-.... и т.д. M>новые класы в другом домене
Хм, VS ругается, мол динамические сборки я могу делать только в текущем модуле. Это и правда так? И как же тогда делать?
З.Ы.: Задолбали меня эти запреты VS — то нельзя, это нельзя... , такое чувство, что то, что я хочу сделать вообще не предназначено для VS&C#......
Re[14]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, 4D man, Вы писали:
4M>Хм, VS ругается, мол динамические сборки я могу делать только в текущем модуле. Это и правда так? И как же тогда делать?
Он ругаеться на то, чт не можен маршалить AssemblyBuilder, т.к. он не помечен Serializible, и не являеться производным от MarshalByRef. Поэтому типы нужно создавать в том домене, который создал, а обратно маршалить уже готовые типы, или еще лучше проводить там работы, которые связанны с временными типами, и обратно возвращать только результаты. Пример:
Здравствуйте, 4D man, Вы писали:
4M>я не пойму, почему он не работает...ведь DynamicDotProductGen() запускаться, по идее, должен уже в новом домене....
запускаеться в старом,т.к. объект класса TestILGenerator передаеться по ссылке. В новом варианте он сериализуеться и вместе с собой сериализует result, который поредаеться по ссылке и остаеться в старом домене из нового он заполняеться сериализуемыми значениями. В результате в старом домене оказываеться result с результатами полученными в новом домене.
PS Пока писал ответ сообщение пропало . Но комментарии не помешают все равно. Надеюсь на этот раз ничего не напутал
ICQ: 446240
Re[9]: книга по Reflection.Emit и модификация классов на лет
M>А нельзя сразу определить весь набор этих перегруженных функций?
4M>??? В том-то и дело, что нет, т.к. во время работы программы набор функций постоянно меняется. Причем кол-во функций теоретически может быть вообще бесконечно большим, сколько в память влезет. Так что заранее сказать, какие там функции будут и сколько их, нельзя....
А обязательно задавать функции именно в этом классе? Может, создавай на каждую функцию отдельный класс, с нужным методом.
Глядишь, тебе основной класс вообще не нужно будет пере-Emit'чивать, только генерировать классы-функции.
... << RSDN@Home 1.0 beta 7a >>
Re[18]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, mihailik, Вы писали:
M>Нужно ещё учитывать, что возня с доменами/маршалингом может съесть все преимущества экономии памяти. Экономика должна быть экономной
Ну если поменьше маршалить, пореже домены(создавать/грохать), если таких динамически создаваемых типов неконечное число и другими способами(не генерация типов) решить задачу не удаеться, то вроде не самый плохой вариант
ICQ: 446240
Re[17]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, Miem, Вы писали:
M>Вот работающий код:
M>[c#] M>class Result :MarshalByRefObject M>{ M> public int X; //Вот тут могуть быть любые сериализуемые типы M> //хоть Type и Serializable, но у него не получаеться десериализоваться (???) M>}
M> Type type = testClass.CreateType(); M> object testObject = System.Activator.CreateInstance(type,new object[]{3});
M> result.X = (int)type.GetField("x").GetValue(testObject);
Ну и опять же мы на выходе получаем только членов полученного класса. Сам же testObject или type вытащить не получается...когда до него доходит уже в текущем, а не в TestDomain домене, ес-но ошибка, т.к. его сборка не видна из текщего домена....
Re[18]: книга по Reflection.Emit и модификация классов на ле
Попробовал вытащить так:
object res = myDomain.CreateInstance("TestAssembly","TestClass");
А он, зараза, пишет:
"File or assembly name TestAssembly, or one of its dependencies, was not found"
Это нормально? Я даже пробовал сохранять сборку. То же самое... только вот после исследования её ILDasm'ом в ней я нашел только манифест, никаких типов....
Re[18]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, 4D man, Вы писали:
4M>Ну и опять же мы на выходе получаем только членов полученного класса. Сам же testObject или type вытащить не получается...когда до него доходит уже в текущем, а не в TestDomain домене, ес-но ошибка, т.к. его сборка не видна из текщего домена....
А чем тебя не устраивает работа с полученным классом в новом домене и возвращение лишь результатов работы? Так даже лучше. Используешь временный домен как рабочую силу и нафиг его потом за ненадобностью. А если серьезно, то попробуй именно так и разделить работу. Основной домен занимается вводом входных данных, генерацией типов во временном домене, и вывод результатов выполнения методов этих типов.
а вообще можно вытащить ссылку на объект, если унаследовать от MarshalByRefObject
но зачем он тебе нужен, если ты не знаешь его типа? (если звать GetType у него, то возвращаеться 'MarshalByRefObject'). Да и тормоза это будут большие. Постоянный маршалинг всех обращений к объекту через границу доменов. Попробовал указать что класс Serializable:
Здравствуйте, Miem, Вы писали:
M>А чем тебя не устраивает работа с полученным классом в новом домене и возвращение лишь результатов работы? Так даже лучше. Используешь временный домен как рабочую силу и нафиг его потом за ненадобностью. А если серьезно, то попробуй именно так и разделить работу. Основной домен занимается вводом входных данных, генерацией типов во временном домене, и вывод результатов выполнения методов этих типов.
Я так и хотел сделать. Но сгенериный тип тогда надо как-то сохранить в его домене, а потом другим методом в этом домене его использовать. Можно сделать конечно так:
private static Type T;
public void Tuser()
{
// работаем с res.X
}
public void DynamicDotProductGen()
{
// генерим тип
res.X = type;
}
А потом где-то: myDomain.DoCallBack(new CrossAppDomainDelegate(Tuser));
Но так мне кажется не очень удобным, да и корявым... Может есть способ получше?
M>PS Если не секрет, то что за задача с такими ужасными требованиями?
Я бы рассказал, да только разъяснения по ней займут ещё такую же большую ветку форума, так что лучше не буду... А если вкратце, то это связано с мат.анализом+ИИ. `
Re[20]: книга по Reflection.Emit и модификация классов на ле
Здравствуйте, 4D man, Вы писали:
4M>Я так и хотел сделать. Но сгенериный тип тогда надо как-то сохранить в его домене, а потом другим методом в этом домене его использовать.
Воспользуйся для хранения данных в домене:
AppDomain.CurrentDomain.SetData и AppDomain.CurrentDomain.GetData
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[3]: книга по Reflection.Emit и модификация классов на лет
Здравствуйте, 4D man, Вы писали:
L>>Интерфейс класса должен менятся или нет? Или должна менятся только его реализация? 4M>В классе всегда одна функция, у неё меняется только реализация, и ещё постоянно добавляются/убираются/модифицируются однотипнюе функции типа 4M>double _имя функции_(double[] args) 4M>У них меняются только название и код, которые вводятся пользователем. 4M>Вот, собственно, и весь интерфейс класса.
Таким образом получается, что интерфейс класса постоянно меняется. Значит проблема в архитектуре. Надо смотреть конкретно на задачу, чтобы решить для себя чем пользоваться — Factory или Decorator.
It's nice to be important, but it's more important to be nice.
Re[21]: книга по Reflection.Emit и модификация классов на ле