Пытаюсь преобразовать один Expression<Func<double, double>>
в другой, однако при попытке компиляции полученного выражения, появляется ошибка
System.InvalidOperationException : На переменную "z" типа "System.Double" имеется
ссылка из области "", но она не определена.
Если я правильно понимаю, то эту проблему можно решить заменив в все ParameterExpression
в исходном Expression
на один и тот же( т.к у меня функция от одной переменной). Подскажите существует ли способ это сделать?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace Reflection.Differentiation
{
public static class Algebra
{
private static Dictionary<ExpressionType, Func<Expression, Expression>> diffFuncs;
private static void InitializeExprDiffFuncs()
{
diffFuncs = new Dictionary<ExpressionType, Func<Expression, Expression>>
{
[ExpressionType.Multiply] = (expr) =>
{
var e = (BinaryExpression)expr;
if (e.Left is ConstantExpression || e.Right is ConstantExpression)
{
var constExpr = (e.Left is ConstantExpression) ? e.Left : e.Right;
var otherExpr = (e.Left is ConstantExpression) ? e.Right : e.Left;
return Expression.Multiply((ConstantExpression)constExpr, diffFuncs[otherExpr.NodeType](otherExpr));
}
else
{
return Expression.Add(
Expression.Multiply(e.Left, diffFuncs[e.Right.NodeType](e.Right)),
Expression.Multiply(e.Right, diffFuncs[e.Left.NodeType](e.Left))
);
}
},
[ExpressionType.Add] = (expr) =>
{
var e = (BinaryExpression)expr;
return Expression.Add(diffFuncs[e.Left.NodeType](e.Left), diffFuncs[e.Right.NodeType](e.Right));
},
[ExpressionType.Call] = (expr) =>
{
var e = (MethodCallExpression)expr;
if (e.Method.Name == "Sin")
{
return Expression.Multiply(
Expression.Call(null, typeof(Math).GetMethod("Cos", new[] { typeof(double) }), e.Arguments[0]),
diffFuncs[e.Arguments[0].NodeType](e.Arguments[0])
);
}
if (e.Method.Name == "Cos")
{
return Expression.Multiply(
Expression.Multiply(
Expression.Call(null, typeof(Math).GetMethod("Sin", new[] { typeof(double) }), e.Arguments[0]),
Expression.Constant((double)-1)
),
diffFuncs[e.Arguments[0].NodeType](e.Arguments[0])
);
}
throw new ArgumentException(expr.ToString() + "have unexpexted call");
},
[ExpressionType.Constant] = (expr) => Expression.Constant((double)0),
[ExpressionType.Parameter] = (expr) => Expression.Constant((double)1)
};
}
static Algebra()
{
InitializeExprDiffFuncs();
}
public static Expression<Func<double, double>> Differentiate(Expression<Func<double, double>> funcExpr)
{
var parameter = Expression.Parameter(typeof(double), "z");
var expr = diffFuncs[funcExpr.Body.NodeType](funcExpr.Body);
var lambda = Expression.Lambda<Func<double, double>>(expr, parameter);
return lambda;
}
}
}
Дело в том, что после всех ваших преобразований в вашем выражении все еще остается переменная z от изначальной лямбды, которая не указана в списке параметров. Вместо нее вы создаете новую переменную, которая хоть и имеет то же самое имя, но нигде в выражении не используется.
Когда вы трансформируете выражение сохраняя переменные в нем - нужно копировать их из старой лямбды в новую:
return Expression.Lambda<Func<double, double>>(expr, funcExpr.Parameters);
Виртуальный выделенный сервер (VDS) становится отличным выбором
С помощью SimpleBrowser заполняю поля логина и пароля и имитирую нажатие кнопки, после чего происходит вход на сайтДалее из объекта извлекаю файлы...
Посоветуйте как без создания дополнительных переменных реализовать такое:
Я создал скрипт C# в котором есть несколько функций и функция ChooseResolution()Прицепил его на пустой объект UIManager, который засунул в поле для объектов...
Вообщем интересует ответ на вопрос , который уже озвучен в заголовке тредаВозможно есть уже готовая реализация или же если подскажите в какую...