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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> как для элементов Delegate[], List<Delegate>, завести тип делегата уже в Runtime-е? 
:(
    Опции темы
marcusmae
Дата 30.8.2006, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



Думал, что хорошо понимаю делегаты, но теперь так не кажется.
Возможны такие конструкции, как Delegate[], List<Delegate>, однако инициализировать их элементы с помощью .CreateDelegate(...) можно только имея тип делегата, то есть например такой

Код

public delegate int delegateType(int arg, params object[] args);


Но это - конкретный тип. Также понятно, что следующий тип подходит вообще всем :

Код

public delegate object delegateCommonType(params object[] args);


Но интересно узнать, возможно ли завести новый тип делегата уже во время исполнения? Может, кто-нибудь хитро переопределил MulticastDelegate и поделится идеей?




--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
wotker
Дата 30.8.2006, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Код

Но интересно узнать, возможно ли завести новый тип делегата уже во время исполнения?


пример взять из книги по сис. программированию на cil
Код


static Function CompileToCS()
{
 ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();
 CompilerParameters parameters = new CompilerParameters();

 parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("Function.dll");
 parameters.GenerateInMemory = true;

  string e = expr.GenerateCS();
  string code = "public class FunctionCS: Function\n"+
    "{\n"+
    "  public override double Eval(double x)\n"+
    "  {\n"+
    "    return "+e+";\n"+
    "  }\n"+
    "}\n";
    
 CompilerResults compilerResults =
 compiler.CompileAssemblyFromSource(parameters,code);
 Assembly assembly = compilerResults.CompiledAssembly;
 return assembly.CreateInstance("FunctionCS") as Function;
}



Я думаю что также можно поступить и с делегатом


--------------------
ICQ ::            347306684e-mail ::         wotker[at]rambler[dot]ru 
PM MAIL ICQ   Вверх
marcusmae
Дата 30.8.2006, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


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

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



хм, да, но здесь вроде бы получается создание заново всего класса. Похожий вариант можно было бы прокрутить созданием динамической сборки на C# (только без исходного кода, а вместо этого либо MSIL-код, либо байт-код)   :

Код

                // construct a dynamic assembly
                Guid g = Guid.NewGuid();
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = "BuilderClass_" + g;
               assemblyBuilder = System.Threading.Thread.GetDomain().
                    DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

                // add  a  dynamic  module
                moduleBuilder_value =
                    assemblyBuilder.DefineDynamicModule("DynamicModule");

                // далее, добавлять типы в этот модуль, а в них - существующие методы


Другое дело, когда метод добавляется в уже существующий класс. Я делаю это с помощью DynamicMethod :

Код

        public void AddMethod(MethodInfo methodInfo, bool skipVisibility)
        {
            // retrieve array of parameters types
            ParameterInfo[] parametersInfo = methodInfo.GetParameters();
            Type[] parameterTypes = new Type[parametersInfo.Length];
            for (int parameterIndex = 0; parameterIndex < parametersInfo.Length;
                parameterIndex++)
                parameterTypes[parameterIndex] =
                    parametersInfo[parameterIndex].ParameterType;

            // check such method adding permission
            MethodInfo sameMethodInfo =
                this.GetType().GetMethod(methodInfo.Name);
            if ((sameMethodInfo != null)&&
                (!sameMethodInfo.ReturnType.Equals(methodInfo.ReturnType)))
                throw new UnsituableMethodReturnType(
                    "Cannot add a method to partially dynamic class because " +
                    "method with such name is already defined, and its " +
                    "return type is different.");

            sameMethodInfo =
                this.GetType().GetMethod(methodInfo.Name, parameterTypes);
            if (sameMethodInfo!=null)
                throw new UnsituableMethodArguments(
                    "Cannot add a method to partially dynamic class because " +
                    "method with such name and arguments is already defined.");

            DynamicMethod dynamicMethod = new DynamicMethod(methodInfo.Name,
                methodInfo.ReturnType , parameterTypes, this.GetType().Module,
                skipVisibility);

            // add dynamic method body
            DynamicILInfo dymanicILInfo = dynamicMethod.GetDynamicILInfo();
            MethodBody methodBody = methodInfo.GetMethodBody();
            dymanicILInfo.SetCode(methodBody.GetILAsByteArray(),
                methodBody.MaxStackSize);

            ....
      }


В конце, где многоточие, нужно создать делегат от dynamicMethod. Если этого не сделать, создание нового метода не будет закончено, и вызвать его будет нельзя.
Загвоздка заключается в невозможности заранее описать тип делегата, который соответствовал бы возвращаемому типу и аргументам добавляемого метода.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
mr.DUDA
Дата 2.9.2006, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Создать делегат, который подходит для вызова метода по сигнатуре, для любого класса ? Хмм... Вряд ли.

З.Ы. а вызвать метод конкретной сигнатуры по имеющейся ссылке на Delegate можно с пом. DynamicInvoke.


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

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


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

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


 




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


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

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