При построении дерева выражений я должен использовать узлы, вызывающие внешние методы, чтобы получить значения, которые выражение затем может продолжить оценку. Эти методы поставляются как Func<T>
, и мой код не знает, откуда они берутся.вызов динамического метода в дереве выражений
Каков наилучший способ выполнения упомянутого вызова? Я пытался что-то вроде этого:
private Dictionary<string, Delegate> _externalSymbols;
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
return Expression.Call(method.Method);
}
, который работает до тех пор, как method
извлеченной из словаря был создан в компиляции. Однако, в случае Func<T>
быть динамическим методом, полученный, например, путем компиляции другое выражение во время выполнения, это не будет работать бросать
ArgumentException: неправильное количество аргументов, поставляемых для вызова метода «Int32 lambda_method (System.Runtime.CompilerServices.ExecutionScope)»
желаемый эффект может быть достигнут путем оборачивания данной функции в одно дополнительное выражение, но это кажется довольно отвратительным по сравнению с тем, что он использовал, чтобы выглядеть следующим образом:
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
Expression mediator = method is Func<double> ?
(Expression)(Expression<Func<double>>)(() => ((Func<double>)method)()) :
(Expression<Func<string>>)(() => ((Func<string>)method)());
return Expression.Invoke(mediator);
}
Кроме того, это вряд ли является расширяемым подходом, если мне нужно добавить поддержку для типов, отличных от double
и string
.
Я хотел бы знать, есть ли лучшие варианты, которые будут работать с динамически создаваемыми методами (предпочтительно применимыми к .NET 3.5).
насчет аргументов? Используют ли эти методы какие-либо аргументы или нет? – nightwatch
@nightwatch Нет аргументов, словарь гарантированно содержит только 'Func' делегаты с T, которые являются либо 'double', либо' string' (список этих типов может потребовать расширения в будущем). –
Я не знаю выражения linq, которые, извините. Но то, что вы делаете, выглядит как динамический вызов с именами методов, которые разрешаются во время выполнения. Может быть, вы можете просто использовать динамический объект в качестве интерфейса для ваших внешних функций? – nightwatch