У меня есть выражение LambdaExpression, которое принимает один объект в качестве параметра и в конечном итоге возвращает объект.
Для целей тестирования, вот Lambda (созданная от руки, чтобы соответствовать тому, что я действительно передаю), которая возвращает DateTime, упакованный в виде объекта.
В целях проработки этого, LambdaExpression принимает XmlNode и возвращает объект.
Он должен возвращать объект, реальный тип возврата может быть любым из: DateTime, bool, int, decimal, XmlDocument [пока что]
Общая идея заключается в том, что где-то глубоко в синтаксическом анализаторе эта лямбда создается, и она извлекает значение из своего входного параметра и возвращает его типизированным, но помещенным в квадрат в объекте.
XmlNode node = null;
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
BlockExpression block = Expression.Block(
typeof(object),
new[] { result },
Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))),
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))));
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression);
Позже в коде мы оцениваем <, <=,>,> =, == и! =, Поэтому мы хотим сравнить результат этого LambdaExpression с другим выражением
Обычно мы можем предположить, что LambdaExpression находится слева от Expression.LessThan
справа может быть любое выражение, но давайте предположим, что оно напечатано.
Это означает, что это может быть ConstantExpression или подобное ... но у него есть тип.
Это означает, что Expression.LessThan [например] завершается неудачей, потому что LambdaExpression при вызове Expression.Invoke возвращает объект, а RHS - это любой тип этого типа.
Предполагая, что тип, помещенный в рамку внутри объекта, возвращенного из LambdaExpression, фактически сопоставим с типом в правой части; например,
(object)5 < 6
Как мне написать выражение, которое может сравнивать упакованный тип с распакованным без сбоя?
Я пробовал различные перестановки в linqpad, в том числе пытался написать это в обычном c # - то есть без выражений, просто вложенный if-then-else, однако я не мог заставить это работать совершенно правильно.
Обычно я бы написал что-то вроде этого:
/*
int i = 3;
object o = (object)i;
int compare = 4;
*/
DateTime dt = DateTime.Now;
object o = (object)dt;
DateTime compare = DateTime.Now.AddSeconds(1);
bool b = false;
if(o.GetType().IsAssignableFrom(compare.GetType()))
{
if(o is int)
{
b = (int)o < (int)(object)compare;
}
if(o is DateTime)
{
b = (DateTime)o < (DateTime)(object)compare;
}
if(o is decimal)
{
b = (decimal)o < (decimal)(object)compare;
}
}
Console.WriteLine(b);
При этом, предполагая, что o и сравнивают на самом деле один и тот же тип и один из них помечен как объект, мы все равно можем выполнить <операцию ... </p>
Поэтому я предполагаю, что мой вопрос заключается в том, как мне написать приведенный выше код, когда у меня есть LambdaExpression слева и Expression справа [если два типа не совпадают, false в результате лучше, чем сбой ]
Надеюсь, кто-то может помочь,
Gareth