Re[4]: книга по Reflection.Emit и модификация классов на лет
От: 4D man Россия  
Дата: 18.06.03 13:11
Оценка:
Здравствуйте, 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 и модификация классов на лет
От: mihailik Украина  
Дата: 19.06.03 08:44
Оценка:
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 и модификация классов на лет
От: mihailik Украина  
Дата: 19.06.03 09:11
Оценка:
4M>Из кода же я понял, что Вы предлагаете
4M>при каждом изменении набора функций заново создавать производный
4M>от Evalution класс с перегруженными функциями. Я же имел ввиду
4M>один раз создать тип класса, а потом только менять его содержимое.

А нельзя сразу определить весь набор этих перегруженных функций?
... << RSDN@Home 1.0 beta 7a >>
Re[8]: книга по Reflection.Emit и модификация классов на лет
От: 4D man Россия  
Дата: 21.06.03 10:41
Оценка:
Здравствуйте, mihailik, Вы писали:

M>А нельзя сразу определить весь набор этих перегруженных функций?


??? В том-то и дело, что нет, т.к. во время работы программы набор функций постоянно меняется. Причем кол-во функций теоретически может быть вообще бесконечно большим, сколько в память влезет. Так что заранее сказать, какие там функции будут и сколько их, нельзя....
Re[9]: книга по Reflection.Emit и модификация классов на лет
От: 4D man Россия  
Дата: 22.06.03 07:58
Оценка:
Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k.
Re[10]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 22.06.03 08:12
Оценка:
Здравствуйте, 4D man, Вы писали:

4M>Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k.

Создавай новые класы в другом домене, как посчитаешь что нужно освободить память грохай домен, создавай новый и все заново
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[11]: книга по Reflection.Emit и модификация классов на ле
От: 4D man Россия  
Дата: 22.06.03 15:59
Оценка:
Здравствуйте, Miem, Вы писали:

M>Здравствуйте, 4D man, Вы писали:


4M>>Попробовал при каждом изменении структуры класса просто заново создавать его. Только вот тут напоролся ещё на одну проблему — как удалять предыдущий класс после создания нового? А то каждая новая версия класса занимает лишние 1.5 мега в памяти — проверял "Дисперчером задач" из Win2k.

M>Создавай новые класы в другом домене, как посчитаешь что нужно освободить память грохай домен, создавай новый и все заново
Понятнетько...
Тогда такой вопрос, возможно глупый, т.к. ещё не успел порыть MSDN по этой теме, — как узнать, сколько память отожрал этот домен, чтобы грохать его когда нужно, а не при каждом новом классе?
Re[12]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 22.06.03 20:42
Оценка:
4M>как узнать, сколько память отожрал этот домен, чтобы грохать его когда нужно, а не при каждом новом классе?

А я тоже не знаю. ИМХО никак. Просто ограничивай количество классов. Найди для себя приемлемое.
А про память смотри Соседний топик
Автор: orangy
Дата: 22.06.03
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[13]: книга по Reflection.Emit и модификация классов на ле
От: 4D man Россия  
Дата: 23.06.03 01:20
Оценка:
Здравствуйте, Miem, Вы писали:

4M>>как узнать, сколько память отожрал этот домен, чтобы грохать его когда нужно, а не при каждом новом классе?


M>А я тоже не знаю. ИМХО никак. Просто ограничивай количество классов. Найди для себя приемлемое.

M>А про память смотри Соседний топик
Автор: orangy
Дата: 22.06.03

Ага, 1-2-3-4-5-казнить!-1-2-.... и т.д.
M>новые класы в другом домене
Хм, VS ругается, мол динамические сборки я могу делать только в текущем модуле. Это и правда так? И как же тогда делать?
З.Ы.: Задолбали меня эти запреты VS — то нельзя, это нельзя... , такое чувство, что то, что я хочу сделать вообще не предназначено для VS&C#......
Re[14]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 05:52
Оценка:
Здравствуйте, 4D man, Вы писали:

4M>Хм, VS ругается, мол динамические сборки я могу делать только в текущем модуле. Это и правда так? И как же тогда делать?

Он ругаеться на то, чт не можен маршалить AssemblyBuilder, т.к. он не помечен Serializible, и не являеться производным от MarshalByRef. Поэтому типы нужно создавать в том домене, который создал, а обратно маршалить уже готовые типы, или еще лучше проводить там работы, которые связанны с временными типами, и обратно возвращать только результаты. Пример:
    class TestILGenerator :MarshalByRefObject
    {
        private  Type resultType;
        public  Type Generate()
        {
            AppDomain myDomain = AppDomain.CreateDomain("asas");
            myDomain.DoCallBack(new CrossAppDomainDelegate(DynamicDotProductGen));
            return resultType;
        }
 
        public  void DynamicDotProductGen() 
        {
            AppDomain myDomain = AppDomain.CurrentDomain;
            AssemblyName myAsmName = new AssemblyName();
            myAsmName.Name = "TestAssembly";
    
            AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                myAsmName, 
                AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder testModule = myAsmBuilder.DefineDynamicModule("TestModule",
                "TestModule.dll");

            TypeBuilder testClass = testModule.DefineType("TestClass",
                TypeAttributes.Public);

            FieldBuilder xField = testClass.DefineField("x", typeof(int),
                FieldAttributes.Public);

            resultType = testClass.CreateType();
        }
    }

4M>З.Ы.: Задолбали меня эти запреты VS — то нельзя, это нельзя... , такое чувство, что то, что я хочу сделать вообще не предназначено для VS&C#......

Потому что ты делаешь странные вещи
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[15]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 07:09
Оценка:
Ерунду написал. Код не правильный. Поторопился, нужно было убегать.
ICQ: 446240
Re[16]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 08:23
Оценка:
Вот работающий код:

class Result :MarshalByRefObject
{
    public int X; //Вот тут могуть быть любые сериализуемые типы
    //хоть Type и Serializable, но у него не получаеться десериализоваться (???)
}

[Serializable]
class TestILGenerator
{
    Result result = new Result();
    public  Result Generate(AppDomain myDomain)
    {
        myDomain.DoCallBack(new CrossAppDomainDelegate(DynamicDotProductGen));
        return result;
    }

    public  void DynamicDotProductGen() 
    {
        Type[] ctorParams = new Type[] { typeof(int)};
        AssemblyName myAsmName = new AssemblyName();
        myAsmName.Name = "TestAssembly";
        AppDomain myDomain = AppDomain.CurrentDomain;

        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
            myAsmName, 
            AssemblyBuilderAccess.RunAndSave);

        ModuleBuilder testModule = myAsmBuilder.DefineDynamicModule("TestModule",
            "TestModule.dll");

        TypeBuilder testClass = testModule.DefineType("TestClass",
            TypeAttributes.Public);

        FieldBuilder xField = testClass.DefineField("x", typeof(int),
            FieldAttributes.Public);

        ConstructorBuilder classCtor = testClass.DefineConstructor(
            MethodAttributes.Public,
            CallingConventions.Standard,
            ctorParams);
        Type objType = Type.GetType("System.Object"); 
        ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);

        ILGenerator ctorIL = classCtor.GetILGenerator();
        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Call, objCtor);
        ctorIL.Emit(OpCodes.Ldarg_0);
        ctorIL.Emit(OpCodes.Ldarg_1);
        ctorIL.Emit(OpCodes.Stfld, xField); 
        ctorIL.Emit(OpCodes.Ret);

        Type type = testClass.CreateType();
        object testObject = System.Activator.CreateInstance(type,new object[]{3});
        
        result.X =  (int)type.GetField("x").GetValue(testObject);
    }
}

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        AppDomain myDomain = AppDomain.CreateDomain("TempDomain");
        Result result = new TestILGenerator().Generate(myDomain);
        AppDomain.Unload(myDomain);
    }
}
ICQ: 446240
Re[17]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 08:53
Оценка:
Здравствуйте, 4D man, Вы писали:

4M>я не пойму, почему он не работает...ведь DynamicDotProductGen() запускаться, по идее, должен уже в новом домене....


запускаеться в старом,т.к. объект класса TestILGenerator передаеться по ссылке. В новом варианте он сериализуеться и вместе с собой сериализует result, который поредаеться по ссылке и остаеться в старом домене из нового он заполняеться сериализуемыми значениями. В результате в старом домене оказываеться result с результатами полученными в новом домене.

PS Пока писал ответ сообщение пропало . Но комментарии не помешают все равно. Надеюсь на этот раз ничего не напутал
ICQ: 446240
Re[9]: книга по Reflection.Emit и модификация классов на лет
От: mihailik Украина  
Дата: 23.06.03 09:03
Оценка:
M>А нельзя сразу определить весь набор этих перегруженных функций?

4M>??? В том-то и дело, что нет, т.к. во время работы программы набор функций постоянно меняется. Причем кол-во функций теоретически может быть вообще бесконечно большим, сколько в память влезет. Так что заранее сказать, какие там функции будут и сколько их, нельзя....


А обязательно задавать функции именно в этом классе? Может, создавай на каждую функцию отдельный класс, с нужным методом.

Глядишь, тебе основной класс вообще не нужно будет пере-Emit'чивать, только генерировать классы-функции.
... << RSDN@Home 1.0 beta 7a >>
Re[18]: книга по Reflection.Emit и модификация классов на ле
От: mihailik Украина  
Дата: 23.06.03 09:06
Оценка:
M>запускаеться в старом,т.к. объект класса TestILGenerator передаеться по ссылке.

Нужно ещё учитывать, что возня с доменами/маршалингом может съесть все преимущества экономии памяти. Экономика должна быть экономной
... << RSDN@Home 1.0 beta 7a >>
Re[19]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 09:40
Оценка: 7 (1)
Здравствуйте, mihailik, Вы писали:

M>Нужно ещё учитывать, что возня с доменами/маршалингом может съесть все преимущества экономии памяти. Экономика должна быть экономной

Ну если поменьше маршалить, пореже домены(создавать/грохать), если таких динамически создаваемых типов неконечное число и другими способами(не генерация типов) решить задачу не удаеться, то вроде не самый плохой вариант
ICQ: 446240
Re[17]: книга по Reflection.Emit и модификация классов на ле
От: 4D man Россия  
Дата: 23.06.03 15:17
Оценка:
Здравствуйте, 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 и модификация классов на ле
От: 4D man Россия  
Дата: 23.06.03 15:40
Оценка:
Попробовал вытащить так:
object res = myDomain.CreateInstance("TestAssembly","TestClass");
А он, зараза, пишет:
"File or assembly name TestAssembly, or one of its dependencies, was not found"
Это нормально? Я даже пробовал сохранять сборку. То же самое... только вот после исследования её ILDasm'ом в ней я нашел только манифест, никаких типов....
Re[18]: книга по Reflection.Emit и модификация классов на ле
От: Miem Россия  
Дата: 23.06.03 16:49
Оценка:
Здравствуйте, 4D man, Вы писали:

4M>Ну и опять же мы на выходе получаем только членов полученного класса. Сам же testObject или type вытащить не получается...когда до него доходит уже в текущем, а не в TestDomain домене, ес-но ошибка, т.к. его сборка не видна из текщего домена....


А чем тебя не устраивает работа с полученным классом в новом домене и возвращение лишь результатов работы? Так даже лучше. Используешь временный домен как рабочую силу и нафиг его потом за ненадобностью. А если серьезно, то попробуй именно так и разделить работу. Основной домен занимается вводом входных данных, генерацией типов во временном домене, и вывод результатов выполнения методов этих типов.

а вообще можно вытащить ссылку на объект, если унаследовать от MarshalByRefObject
TypeBuilder testClass = testModule.DefineType("TestClass",
 TypeAttributes.Public, typeof(MarshalByRefObject));
.....
.....
Type objType = Type.GetType("System.MarshalByRefObject"); 
   ConstructorInfo objCtor = objType.GetConstructors(BindingFlags.NonPublic 
        | BindingFlags.Instance)[0];

но зачем он тебе нужен, если ты не знаешь его типа? (если звать GetType у него, то возвращаеться 'MarshalByRefObject'). Да и тормоза это будут большие. Постоянный маршалинг всех обращений к объекту через границу доменов. Попробовал указать что класс Serializable:
TypeBuilder testClass = testModule.DefineType("TestClass",
    TypeAttributes.Public | TypeAttributes.Serializable);

Но тут у него проблемы со сборкой при десериализации. В общем нужно химичить со сборкой. Как-то заставить ее быть "правильнее".

PS Если не секрет, то что за задача с такими ужасными требованиями?
`
... << RSDN@Home 1.0 beta 7 >>
ICQ: 446240
Re[19]: книга по Reflection.Emit и модификация классов на ле
От: 4D man Россия  
Дата: 24.06.03 10:40
Оценка:
Здравствуйте, Miem, Вы писали:

M>А чем тебя не устраивает работа с полученным классом в новом домене и возвращение лишь результатов работы? Так даже лучше. Используешь временный домен как рабочую силу и нафиг его потом за ненадобностью. А если серьезно, то попробуй именно так и разделить работу. Основной домен занимается вводом входных данных, генерацией типов во временном домене, и вывод результатов выполнения методов этих типов.


Я так и хотел сделать. Но сгенериный тип тогда надо как-то сохранить в его домене, а потом другим методом в этом домене его использовать. Можно сделать конечно так:

private static Type T;

public void Tuser()
{
// работаем с res.X
}

public void DynamicDotProductGen()
{
// генерим тип
res.X = type;
}

А потом где-то: myDomain.DoCallBack(new CrossAppDomainDelegate(Tuser));

Но так мне кажется не очень удобным, да и корявым... Может есть способ получше?

M>PS Если не секрет, то что за задача с такими ужасными требованиями?

Я бы рассказал, да только разъяснения по ней займут ещё такую же большую ветку форума, так что лучше не буду... А если вкратце, то это связано с мат.анализом+ИИ. `
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.