Вызов конструктора после GetUninitializedObject
От: LWhisper  
Дата: 29.02.16 08:42
Оценка:
Всем привет!

Продолжаю разрабатывать тему сериализации и десериализации объектов.
Подскажите, пожалуйста — возможно ли "доконструировать" объект после его создания посредством вызова GetUninitializedObject?
То бишь вызвать конструктор (именно конструктор!) с параметром, после создания экземпляра объекта?

Пожалуйста, обратите внимание, что речь идёт только о вызове конструктора. Вызов помеченного специальным аттрибутом метода Initialize не рассматривается. Решается конкретная задача. Спасибо!
serialization il emit getuninitializedobject ctor expression reflection .net csharp
Re: Вызов конструктора после GetUninitializedObject
От: Sinix  
Дата: 29.02.16 10:03
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>Подскажите, пожалуйста — возможно ли "доконструировать" объект после его создания посредством вызова GetUninitializedObject?

LW>То бишь вызвать конструктор (именно конструктор!) с параметром, после создания экземпляра объекта?

В валидном IL — нет. Точнее, можно, но для этого надо не извращаться, а просто сделать пару .newobj + .ret.

В невалидном — просто сгенерить вызов конструктора на положенном в стек объекте. Если повезёт — рантайм пропустит. Но я бы на это не закладывался.
Re[2]: Вызов конструктора после GetUninitializedObject
От: LWhisper  
Дата: 29.02.16 10:11
Оценка:
Здравствуйте, Sinix, Вы писали:

S>В валидном IL — нет. Точнее, можно, но для этого надо не извращаться, а просто сделать пару .newobj + .ret.

Очень жаль, спасибо.

S>В невалидном — просто сгенерить вызов конструктора на положенном в стек объекте. Если повезёт — рантайм пропустит. Но я бы на это не закладывался.

Заманчиво, но завязываться действительно не стоит. Возьму на заметку, вдруг когда пригодится.
Re: Вызов конструктора после GetUninitializedObject
От: vorona  
Дата: 29.02.16 15:50
Оценка: 49 (3)
Здравствуйте, LWhisper, Вы писали:

using System;
using System.Runtime.Serialization;

namespace ConsoleApplication1
{
    class A
    {
        public A(string param)
        {
            Console.WriteLine(param);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IntPtr ctor = typeof(A).GetConstructor(new Type[] { typeof(String) }).MethodHandle.GetFunctionPointer();
            var actionCtor = typeof(Action<Object, String>).GetConstructor(new Type[] { typeof(Object), typeof(IntPtr) });
            var ctorDelegate = (Action<Object, String>)actionCtor.Invoke(new Object[] { null, ctor });

            var a = (A)FormatterServices.GetUninitializedObject(typeof(A));
            ctorDelegate(a, "Hello world!");
        }
    }
}
Re[2]: Вызов конструктора после GetUninitializedObject
От: desco США http://v2matveev.blogspot.com
Дата: 01.03.16 05:59
Оценка: 7 (2)
можно короче

using System;
using System.Runtime.Serialization;

namespace ConsoleApplication1
{
    class A
    {
        public A(string param)
        {
            Console.WriteLine(param);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var a = (A)FormatterServices.GetUninitializedObject(typeof(A));
            var ctor = typeof(A).GetConstructor(new[] { typeof(string) });
            ctor.Invoke(a, new[] { "123" });
        }
    }
}
Re[2]: Вызов конструктора после GetUninitializedObject
От: LWhisper  
Дата: 01.03.16 08:07
Оценка:
Здравствуйте, vorona, Вы писали:

V>Здравствуйте, LWhisper, Вы писали:


V>
V>using System;
V>using System.Runtime.Serialization;

V>namespace ConsoleApplication1
V>{
V>    class A
V>    {
V>        public A(string param)
V>        {
V>            Console.WriteLine(param);
V>        }
V>    }

V>    class Program
V>    {
V>        static void Main(string[] args)
V>        {
V>            IntPtr ctor = typeof(A).GetConstructor(new Type[] { typeof(String) }).MethodHandle.GetFunctionPointer();
V>            var actionCtor = typeof(Action<Object, String>).GetConstructor(new Type[] { typeof(Object), typeof(IntPtr) });
V>            var ctorDelegate = (Action<Object, String>)actionCtor.Invoke(new Object[] { null, ctor });

V>            var a = (A)FormatterServices.GetUninitializedObject(typeof(A));
V>            ctorDelegate(a, "Hello world!");
V>        }
V>    }
V>}
V>


Вау! Спасибо огромное!
Живём!
Re[3]: Вызов конструктора после GetUninitializedObject
От: LWhisper  
Дата: 01.03.16 08:12
Оценка:
Здравствуйте, desco, Вы писали:

D>можно короче


D>
D>using System;
D>using System.Runtime.Serialization;

D>namespace ConsoleApplication1
D>{
D>    class A
D>    {
D>        public A(string param)
D>        {
D>            Console.WriteLine(param);
D>        }
D>    }

D>    class Program
D>    {
D>        static void Main(string[] args)
D>        {
D>            var a = (A)FormatterServices.GetUninitializedObject(typeof(A));
D>            var ctor = typeof(A).GetConstructor(new[] { typeof(string) });
D>            ctor.Invoke(a, new[] { "123" });
D>        }
D>    }
D>}
D>

Мне в любом случае придётся это кэшировать, заворачивать в Expression, и возвращать как лямбда-функции вида Func<object, object, ...>, но в любом случае — спасибо. :]
Отредактировано 01.03.2016 8:14 LWhisper . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.