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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C#, динамическое создание объекта. 
:(
    Опции темы
NightmareZ
Дата 12.8.2009, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


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

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



Есть некоторые объекты некоторых типов. 
У этих объектов есть свойства. Некоторым свойствам задан атрибут [A]. 

Нужно в рантайме создавать прокси-объекты, которые будут иметь одноимённые свойства вышеназванных объектов, но лишь те, у которых задан атрибут [A]. Обращения к этим свойствам прокси-объектов должны переадресовываться. Ну т.е.:

Код

class MyAttrib : Attribute { }

class MyClass
{
    public A { get; set; }
    public B { get; set; }

    [MyAttrib]
    public C { get; set; }
    
    public D { get; set; }
}

MyClass obj = new MyClass();


Для объекта obj в рантайме должен быть создан прокси-объект соответствующий следующему классу:

Код

class MyProxy
{
    private MyClass obj;
    public MyProxy(MyClass obj) { this.obj = obj; }

    public C
    {
        get { return obj.C; }
        set { obj.C = value; }
    }
}


Как это сделать?


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
NightmareZ
Дата 12.8.2009, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


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

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



В принципе, я уже сделал то, что хотел. Мож кто какие замечания скажет?

Код

public object CreateProxy()
{
    // Создаём сборку.
    var asmName = new AssemblyName("GlyphProxyAssembly.dll");
    AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
        asmName, AssemblyBuilderAccess.Run);
    ModuleBuilder moduleBuilder = assembly.DefineDynamicModule(asmName.Name);

    // Прокси-класс.
    TypeBuilder typeBuilder = moduleBuilder.DefineType("GlyphProxy" + Guid.NewGuid(), TypeAttributes.Class | TypeAttributes.Public, typeof(object));
    
    // Приватное поле, содержащее ссылку на объект, с которым связан данный прокси.
    FieldBuilder ownerField = typeBuilder.DefineField("_owner", GetType(), FieldAttributes.Private);

    // Ищем все поля в данном объекте, помеченные атрибутом ActivePropertyAttribute
    // и создаём соответствующие поля в прокси объекте.
    foreach (var prop in GetType().GetProperties())
        foreach (var attrib in prop.GetCustomAttributes(true))
            if (attrib is ActivePropertyAttribute)
            {
                // Свойство.
                PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(prop.Name,
                    PropertyAttributes.HasDefault,
                    prop.PropertyType,
                    null);

                // Геттер.
                MethodBuilder methodGet = typeBuilder.DefineMethod("Get_" + prop.Name,
                    MethodAttributes.Public,
                    prop.PropertyType,
                    new Type[] { });

                // Код геттера: берём значение свойства из связанного объекта.
                ILGenerator ilGet = methodGet.GetILGenerator();

                ilGet.Emit(OpCodes.Ldarg_0);
                ilGet.Emit(OpCodes.Ldfld, ownerField);
                ilGet.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null);
                ilGet.Emit(OpCodes.Ret);

                // Сеттер.
                MethodBuilder methodSet = typeBuilder.DefineMethod("Set_" + prop.Name,
                    MethodAttributes.Public,
                    null,
                    new[] { prop.PropertyType });

                // Код сеттера: сохраняем значение свойства в связанный объект.
                ILGenerator ilSet = methodSet.GetILGenerator();

                ilSet.Emit(OpCodes.Ldarg_0);
                ilSet.Emit(OpCodes.Ldfld, ownerField);
                ilSet.Emit(OpCodes.Ldarg_1);
                ilSet.EmitCall(OpCodes.Callvirt, prop.GetSetMethod(), new[] { prop.PropertyType });
                ilSet.Emit(OpCodes.Ret);

                // Назначем геттер и сеттер свойству.
                propertyBuilder.SetGetMethod(methodGet);
                propertyBuilder.SetSetMethod(methodSet);

                break;
            }

    // Конструктор прокси-класса.
    var ctorParams = new[] { GetType() };
    ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorParams);
    ILGenerator ilgen = constructorBuilder.GetILGenerator();

    // Вызываем конструктор родителя.
    ilgen.Emit(OpCodes.Ldarg_0);
    ilgen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0]));

    // Загружаем ссылку на объект, с которым связан данный прокси в приватное поле.
    ilgen.Emit(OpCodes.Ldarg_0);
    ilgen.Emit(OpCodes.Ldarg_1);
    ilgen.Emit(OpCodes.Stfld, ownerField);

    ilgen.Emit(OpCodes.Ret);
            
    // Создаём и возвращаем тип прокси-объекта.
    Type type = typeBuilder.CreateType();
    return Activator.CreateInstance(type, new object[] { this });
}


Это сообщение отредактировал(а) NightmareZ - 12.8.2009, 22:55


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
mihryak
Дата 13.8.2009, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



глянь сюда
и можно ещё погуглить на тему dynamic proxy, довольно много вариантов (пару лет назад решал схожий вопрос)
PM MAIL ICQ   Вверх
Partizan
Дата 13.8.2009, 00:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


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

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



а ещё с TypeDescriptor/PropertyDescriptor-ами поиграться можно и всё такое)

http://forum.vingrad.ru/forum/topic-237160...y1708799/0.html


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 13.8.2009, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



А зачем это вообще надо? Динамически создавать в рантайме класс, структура которого известна уже во время разработки... не понятно. Если надо скрыть структуру класса, а предоставить внешним сборкам ограниченный набор членов, то для этого есть интерфейсы. Чего-то в этом роде вполне достаточно.
Код

    public interface IMyProxy
    {
        int C { get; set; }
    }
    internal class MyClass : IMyProxy
    {
        internal int A { get; set; }
        internal int B { get; set; }
        internal int D { get; set; }

        #region Члены IMyProxy

        int IMyProxy.C { get; set; }

        #endregion
    }


Для того, чтобы вовнешней сборке можно было получить экземпляр такого класса нужен какой-нибудь специальный метод, который будет возвращать интерфейс
Код

        public static IMyProxy CreateMyProxy()
        {
            var mc = new MyClass();
            return (IMyProxy)mc;
        }

ИМХО - этого вполне достаточно. Или я не правильно задачу понял?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
mihryak
Дата 13.8.2009, 02:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(diadiavova @  13.8.2009,  01:47 Найти цитируемый пост)
А зачем это вообще надо?

в моей ссылке в качестве примера показано прикручивание автоматической валидации и форматирования возвращаемого значение
довольно удобно ведь лишь выставить св-ву или методу атрибут, чтобы всё это получить, в результате может получиться нечто вроде аспектно-ориентированного программирования (тут уж от целей и применения зависит)

Это сообщение отредактировал(а) mihryak - 13.8.2009, 02:38
PM MAIL ICQ   Вверх
diadiavova
Дата 13.8.2009, 02:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



Цитата(mihryak @  13.8.2009,  03:37 Найти цитируемый пост)
в результате может получиться нечто вроде аспектно-ориентированного программирования

Тогда можно и так
http://www.postsharp.org/

Добавлено через 2 минуты и 6 секунд
Ток чойт есть подозрение, что там дело совсем в другом.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
NightmareZ
Дата 13.8.2009, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


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

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



Цитата(diadiavova @  13.8.2009,  00:47 Найти цитируемый пост)
А зачем это вообще надо? Динамически создавать в рантайме класс, структура которого известна уже во время разработки... не понятно.


Очевидно, это нужно, потому что структура классов изначально неизвестна.


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
diadiavova
Дата 13.8.2009, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



Цитата(NightmareZ @  13.8.2009,  13:37 Найти цитируемый пост)
Очевидно, это нужно, потому что структура классов изначально неизвестна. 

Ясн. А (любопытства ради)...зачем это надо?


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
NightmareZ
Дата 13.8.2009, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


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

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



Цитата(diadiavova @  13.8.2009,  13:14 Найти цитируемый пост)
Ясн. А (любопытства ради)...зачем это надо?


http://www.gamedev.ru/code/forum/?id=122293


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
diadiavova
Дата 13.8.2009, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



На сколько я знаю BrowsableAttributes в гриде работает нормально. Что значит "дёргаются все свойства"? 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
NightmareZ
Дата 13.8.2009, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


[хакер]
**


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

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



Цитата(diadiavova @  13.8.2009,  13:41 Найти цитируемый пост)
На сколько я знаю BrowsableAttributes в гриде работает нормально. Что значит "дёргаются все свойства"? 


Это значит, что отображаются только те свойства, у которых есть атрибуты, указанные в BrowsableAttributes, но читаются значения всех паблик свойств. Мне не нужно, чтобы все читались.


--------------------
NightmareZ.net - мой блог и сайт, мои проекты и прочий трэш
Ely-Art.ru - наша маленькая домашняя арт-студия
mugcraft.ru - кружки на любой вкус
PM WWW ICQ Skype GTalk AOL YIM   Вверх
diadiavova
Дата 13.8.2009, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



Проверил - действительно "дёргается", но тут способ, предложенный партизаном, вполне решает проблему.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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