2012-04-17 4 views
1

У меня есть ситуация, когда у меня есть объект типа «динамический», который является invokable. Я пытаюсь реализовать функцию, которая будет динамически вызывать объект во время выполнения с набором аргументов. Достаточно легко вызвать его, если я знаю, что количество аргументов во время компиляции:Можно ли вызвать динамический объект в C#?

Object StaticInvoke(dynamic func, Object[] args) { 
    // arguments are explicitly unwrapped and bound to the invokation 
    // requiring that we know the number at compile time 
    return func(args[0], args[1], ...); 
} 

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

static Object Invoke(dynamic func, Object[] args) 
{ 

    // not sure what to put here 
    switch(args.Length) 
    { 
     case 0: 
      return func(); 
     case 1: 
      return func(args[0]); 
     case 2: 
      return func(args[0], args[1]); 
     ... 
     default: 
      throw new NotSupportedException(); 
    } 
} 

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

Я в основном пытаюсь реализовать функцию «применить» в C#. Есть ли более простой способ выполнить то, что я пытаюсь сделать? Я чувствую, что мне не хватает чего-то очевидного.

+1

Почему пользователи вашего кода вызывают 'Invoke' вместо прямого вызова функции func (...)'? –

+0

Я подозреваю, что есть встроенный способ сделать то, что вы пытаетесь сделать, используя отражение, но я не эксперт в этой области. Вместо этого я упомянул, что если вы хотите использовать переменное число аргументов в C#, вы должны посмотреть ключевое слово 'params'. Мое оговорку заключается в том, что я не думаю, что вы действительно хотите 'params', вы хотите вызвать метод с использованием отражения. –

+0

@ M.Babcock: «invoke», который я пытаюсь создать, реализует метод интерфейса, чтобы мы могли работать с новыми динамическими вызовами так же, как мы работаем с «устаревшими» вызовами в старых сценариях, которые мы используем. – MarkPflug

ответ

1

с открытым исходным кодом Apache лицензированы ImpromptuInterface (на NuGet) имеет статический метод Impromptu.Invoke, который делает это. Вы можете посмотреть на реализацию, в то время как она обрабатывает произвольное количество аргументов, она также работает, что вам, вероятно, не нужно, например, предоставить механизм динамически описываемых именованных аргументов и вызвать их.

Идея вашего коммутатора может фактически быть способом перехода в зависимости от вашего использования, поскольку оно должно быть простым и быстрым.

С вашим корпусом коммутатора, при котором N является наибольшим числом аргументов, которые вы поддерживаете, компилятор C# создаст N + 1 callites, которые он просто статически знает, где они находятся. Impromptu будет вызывать dlr apis, как и компилятор, но будет storing the callsite in a hashtable, который добавит время поиска (неплохо, хотя).

dlr api также требует, чтобы делегат имел подпись, которая соответствует числу или аргументам, которые вы вызываете, снова компилятор будет уверен, что у вас статически есть N + 1 делегатов, тогда как Impromptu будет использовать 17 встроенных Func < > в случае с коммутатором, а затем start emiting new delegates as needed, это одноразовая тяжелая работа для генерации, а затем добавляет больше обращений к хэш-таблице для последующих вызовов.

+0

Импровизированный материал выглядит немного переполненным тем, что мне нужно.Я думаю, что переключатель будет достаточно хорошим. Спасибо за информацию! – MarkPflug

0

EDIT: Это не ответ - удерживая его здесь, чтобы сообщить другим, что маловероятно, что @Mark ищет.

Для обычных объектов, которые вы будете использовать MethodBase.InvokeMethod:

MethodInfo magicMethod = magicType.GetMethod("ItsMagic"); 
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100}); 
+0

Нет; он пытается использовать 'IDynamicMetaObjectProvider'. – SLaks

Смежные вопросы