Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Reflection.Emit, Создание статитческого конструктора 
:(
    Опции темы
jfx
  Дата 28.7.2005, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 18.10.2004

Репутация: 1
Всего: 1



Есть проблема.
Нужно создать сборку с одним классом в котором присутствует одно public static поле, с данными.
Поэтому встает проблема с .cctor Информации в практически нет на эту тему smile

Значит так, попорядку.
Я создаю сборку в ней модуль в ней тип, далее поле. Ок тут проблем нет. Далее создаю .cctor и мне нужно проинициализировать созданное поле.

Как я пытаюсь сделать: откомпилил класс как он должен быть, прогнал его через ildasm и теперь пытаюсь повторить то что получилось.

Проблемы возникают с <PrivateImplementationDetails> структурой и данными собственно. Как их создать.
С этим ладно кое как криво но что-то получилось. Далее мне нужно теперь мне нужно загрузить в стек token этой структуры и вот тут я совсем не знаю что делать smile

Люди добрые помогите. Может я плохо искал и где-то есть подробная информация как инициализировать статическое поле? Или можно это делать как-то иначе?

Спасибо.

PM MAIL   Вверх
mr.DUDA
Дата 28.7.2005, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Вот такой исходный код:
Код
using System;

namespace ClassLibrary1
{
    public class Class1
    {
        public Class1()
        {
        }

        public static string Str = "123";


        static int i;
        static Class1()
        {
            i = 2;
        }
    }
}


Превращается в вот такой IL-код:
Код
.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
  .maxstack 1
  ldstr "123"
  stsfld string ClassLibrary1.Class1::Str
  ldc.i4.2 
  stsfld int32 ClassLibrary1.Class1::i
  ret 
}


Может, это хоть чем-то поможет.


--------------------
user posted image
PM MAIL WWW   Вверх
jfx
Дата 28.7.2005, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 18.10.2004

Репутация: 1
Всего: 1



Спасибо за ответ, но видимо я не совсем точно выразился.

Есть вот такой класс:

Код

    public class Class1
    {
        public static byte[] Data = new byte[] {1,2,3};
    }


После копиляции он превращается вот в это:

Код

{
  .class public auto ansi Class1
         extends [mscorlib]System.Object
  {
    .field public static unsigned int8[] Data
    .method private hidebysig specialname rtspecialname static 
            void  .cctor() cil managed
    {
      // Code size       23 (0x17)
      .maxstack  3
      IL_0000:  ldc.i4.3
      IL_0001:  newarr     [mscorlib]System.Byte
      IL_0006:  dup
      IL_0007:  ldtoken    field valuetype '<PrivateImplementationDetails>'/'$$struct0x6000001-1' '<PrivateImplementationDetails>'::'$$method0x6000001-1'
      IL_000c:  call       void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
                                                                                                          valuetype [mscorlib]System.RuntimeFieldHandle)
      IL_0011:  stsfld     unsigned int8[] Class1::Data
      IL_0016:  ret
    } // end of method Class1::.cctor

    .method public hidebysig specialname rtspecialname 
            instance void  .ctor() cil managed
    {
      // Code size       7 (0x7)
      .maxstack  1
      IL_0000:  ldarg.0
      IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
      IL_0006:  ret
    } // end of method Class1::.ctor

  } // end of class Class1



.class private auto ansi '<PrivateImplementationDetails>'
       extends [mscorlib]System.Object
{
  .class explicit ansi sealed nested private '$$struct0x6000001-1'
         extends [mscorlib]System.ValueType
  {
    .pack 1
    .size 3
  } // end of class '$$struct0x6000001-1'

  .field static assembly valuetype '<PrivateImplementationDetails>'/'$$struct0x6000001-1' '$$method0x6000001-1' at D_00002050
} // end of class '<PrivateImplementationDetails>'

.data D_00002050 = bytearray (
                 01 02 03) 


Мне же нужно воспроизвести все это с помощью Reflection.Emit
Вопросы связанные с созданием сборкои, модуля, класса и поля решены (это несложно). Не решенным остался вопрос с инициализацией этого самого статического поля.

Т.е. я делая статический конструктор и из него пытаюсь инициализировать поле (возможно есть более простой способ, но я о мен ничего не знаю).

Примерно это выглядит так:

Код

public static bool SaveAssembly(string storePath, byte[] data)
        {
            if (storePath != null && storePath != string.Empty)
            {
                AssemblyName asmName = new AssemblyName();
                
                asmName.Name = "Test.Class";
                //asmName.KeyPair = "";
                asmName.Version = new Version("0.0.0.0");

                AssemblyBuilder asmBuild = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Save, storePath);
                asmBuild.DefineVersionInfoResource("product", "version", "company", "copyright", "trademark");
                
                ModuleBuilder modBuild = asmBuild.DefineDynamicModule("Test.Class.dll", "Test.Class.dll", false);

                TypeBuilder typeBuild = modBuild.DefineType("ns.Class1", TypeAttributes.Public | TypeAttributes.BeforeFieldInit);

                FieldBuilder fieldBuild = typeBuild.DefineField("Data", typeof(byte[]), FieldAttributes.Public | FieldAttributes.Static);

                typeBuild.DefineInitializedData("__data", data, FieldAttributes.Static);

                ConstructorBuilder сctorBuild = typeBuild.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, new Type[0]);
                ILGenerator cctorIL = сctorBuild.GetILGenerator();

                cctorIL.Emit(OpCodes.Ldc_I4_3);
                cctorIL.Emit(OpCodes.Newarr, typeof(byte) );
                cctorIL.Emit(OpCodes.Dup);
                //cctorIL.Emit( OpCodes.Ldtoken,
                cctorIL.Emit(OpCodes.Ret);

                typeBuild.CreateType();
                asmBuild.Save("Test.Class.dll");

                return true;
            }

            return false;
        }


Что делать дальше я не пойму.
PM MAIL   Вверх
Guest
Дата 28.7.2005, 19:27 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











FieldBuilder dataField = pointTypeBld.DefineField("Data",typeof(byte[]),FieldAttributes.Public | FieldAttributes.Static);
  Вверх
Guest
Дата 28.7.2005, 21:15 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Like this:

// Code size 13 (0xd)
.maxstack 3
IL_0000: ldc.i4.3
IL_0001: newarr [mscorlib]System.Byte
IL_0006: dup
IL_0007: ldtoken field valuetype $ArrayType$3 ns.Class1::Data
IL_000c: ret
  Вверх
Guest
Дата 28.7.2005, 21:22 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











The quickest way to do this is instead of:

FieldBuilder fieldBuild = typeBuild.DefineField("Data", typeof(byte[]), FieldAttributes.Public | FieldAttributes.Static);
typeBuild.DefineInitializedData("__data", data, FieldAttributes.Static);

use the following:

FieldBuilder fieldBuild = typeBuild.DefineInitializedData("Data", data, FieldAttributes.Public | FieldAttributes.Static);
.
.
.
cctorIL.Emit(OpCodes.Ldc_I4_3);
cctorIL.Emit(OpCodes.Newarr,typeof(System.Byte));
cctorIL.Emit(OpCodes.Dup);
cctorIL.Emit(OpCodes.Ldtoken,fieldBuild);
cctorIL.Emit(OpCodes.Ret);

  Вверх
jfx
Дата 28.7.2005, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 18.10.2004

Репутация: 1
Всего: 1



thanks, i will try.
PM MAIL   Вверх
jfx
Дата 29.7.2005, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 18.10.2004

Репутация: 1
Всего: 1



Thanks, it's work.
One more question: How i can call InitializeArray?

PM MAIL   Вверх
Guest
Дата 31.7.2005, 16:31 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











You should use
cctorIL.EmitCall(OpCodes.Call,...,null);
  Вверх
jfx
Дата 6.8.2005, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 18.10.2004

Репутация: 1
Всего: 1



Все получилось. Проблема была в том что я пытался передать методу параметры, а нужно было передать только их тип (параметры то уже в стеке smile ). Окончательно это выглядит так:

Код

        public static bool SaveAssembly(string storePath, byte[] keyPair, byte[] data)
        {
            if (storePath != null && storePath != string.Empty)
            {
                try
                {
                    AssemblyName asmName = new AssemblyName();
                
                    asmName.Name = "Class.Test";
                    asmName.KeyPair = new StrongNameKeyPair(keyPair);
                    asmName.Version = new Version("0.0.0.0");

                    AssemblyBuilder asmBuild = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Save, storePath);
                    asmBuild.DefineVersionInfoResource("Class.Test", "0.0.0.0", "", "", "");
                
                    ModuleBuilder modBuild = asmBuild.DefineDynamicModule("Class.Test.dll", "Class.Test.dll", false);

                    TypeBuilder typeBuild = modBuild.DefineType("Class1", TypeAttributes.Public);
                    FieldBuilder fieldBuild = typeBuild.DefineField("Data", typeof(byte[]), FieldAttributes.Public | FieldAttributes.Static);

                    FieldInfo __data = typeBuild.DefineInitializedData("__data", data, FieldAttributes.Static);

                    ConstructorBuilder сctorBuild = typeBuild.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, new Type[0]);
                    ILGenerator cctorIL = cctorBuild.GetILGenerator();

                    cctorIL.Emit(OpCodes.Ldc_I4, data.Length);
                    cctorIL.Emit(OpCodes.Newarr, typeof(byte) );
                    cctorIL.Emit(OpCodes.Dup);
                    cctorIL.Emit(OpCodes.Ldtoken, __data);

                    MethodInfo initArray = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray", new Type[] {typeof(System.Array), typeof(System.RuntimeFieldHandle)});

                    cctorIL.EmitCall(OpCodes.Call, initArray, null);
                    cctorIL.Emit(OpCodes.Stsfld, fieldBuild);

                    cctorIL.Emit(OpCodes.Ret);
                    typeBuild.CreateType();
                    asmBuild.Save("Class.Test.dll");

                    return true;
                }
                catch
                {
                    return false;
                }
            }
            return false;
        }


Всем спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0522 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.