You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1146 lines
65 KiB
1146 lines
65 KiB
#if NET20 || NET30 || !NET_4_6 |
|
|
|
// Copyright (c) Microsoft. All rights reserved. |
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information. |
|
|
|
using System.Diagnostics; |
|
using System.Dynamic.Utils; |
|
using System.Reflection; |
|
using System.Runtime.CompilerServices; |
|
using LinqInternal.Core; |
|
|
|
namespace System.Linq.Expressions.Reimplement |
|
{ |
|
/// <summary> |
|
/// Represents an expression that has a unary operator. |
|
/// </summary> |
|
[DebuggerTypeProxy(typeof(UnaryExpressionProxy))] |
|
public sealed class UnaryExpression : Expression |
|
{ |
|
private readonly Expression _operand; |
|
private readonly MethodInfo _method; |
|
private readonly ExpressionType _nodeType; |
|
private readonly Type _type; |
|
|
|
internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) |
|
{ |
|
_operand = expression; |
|
_method = method; |
|
_nodeType = nodeType; |
|
_type = type; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.) |
|
/// </summary> |
|
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns> |
|
public override Type Type |
|
{ |
|
get { return _type; } |
|
} |
|
|
|
/// <summary> |
|
/// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.) |
|
/// </summary> |
|
/// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns> |
|
public override ExpressionType NodeType |
|
{ |
|
get { return _nodeType; } |
|
} |
|
|
|
/// <summary> |
|
/// Gets the operand of the unary operation. |
|
/// </summary> |
|
/// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns> |
|
public Expression Operand |
|
{ |
|
get { return _operand; } |
|
} |
|
|
|
/// <summary> |
|
/// Gets the implementing method for the unary operation. |
|
/// </summary> |
|
/// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns> |
|
public MethodInfo Method |
|
{ |
|
get { return _method; } |
|
} |
|
|
|
/// <summary> |
|
/// Gets a value that indicates whether the expression tree node represents a lifted call to an operator. |
|
/// </summary> |
|
/// <returns>true if the node represents a lifted call; otherwise, false.</returns> |
|
public bool IsLifted |
|
{ |
|
get |
|
{ |
|
if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) |
|
{ |
|
return false; |
|
} |
|
var operandIsNullable = _operand.Type.IsNullableType(); |
|
var resultIsNullable = Type.IsNullableType(); |
|
if (_method != null) |
|
{ |
|
return (operandIsNullable && _method.GetParameters()[0].ParameterType != _operand.Type) || |
|
(resultIsNullable && _method.ReturnType != Type); |
|
} |
|
return operandIsNullable || resultIsNullable; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type. |
|
/// </summary> |
|
/// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns> |
|
public bool IsLiftedToNull |
|
{ |
|
get { return IsLifted && Type.IsNullableType(); } |
|
} |
|
|
|
protected internal override Expression Accept(ExpressionVisitor visitor) |
|
{ |
|
return visitor.VisitUnary(this); |
|
} |
|
|
|
/// <summary> |
|
/// Gets a value that indicates whether the expression tree node can be reduced. |
|
/// </summary> |
|
public override bool CanReduce |
|
{ |
|
get |
|
{ |
|
switch (_nodeType) |
|
{ |
|
case ExpressionType.PreIncrementAssign: |
|
case ExpressionType.PreDecrementAssign: |
|
case ExpressionType.PostIncrementAssign: |
|
case ExpressionType.PostDecrementAssign: |
|
return true; |
|
} |
|
return false; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Reduces the expression node to a simpler expression. |
|
/// If CanReduce returns true, this should return a valid expression. |
|
/// This method is allowed to return another node which itself |
|
/// must be reduced. |
|
/// </summary> |
|
/// <returns>The reduced expression.</returns> |
|
public override Expression Reduce() |
|
{ |
|
if (CanReduce) |
|
{ |
|
switch (_operand.NodeType) |
|
{ |
|
case ExpressionType.Index: |
|
return ReduceIndex(); |
|
|
|
case ExpressionType.MemberAccess: |
|
return ReduceMember(); |
|
|
|
default: |
|
return ReduceVariable(); |
|
} |
|
} |
|
return this; |
|
} |
|
|
|
private bool IsPrefix |
|
{ |
|
get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; } |
|
} |
|
|
|
private UnaryExpression FunctionalOp(Expression operand) |
|
{ |
|
ExpressionType functional; |
|
if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) |
|
{ |
|
functional = ExpressionType.Increment; |
|
} |
|
else |
|
{ |
|
functional = ExpressionType.Decrement; |
|
} |
|
return new UnaryExpression(functional, operand, operand.Type, _method); |
|
} |
|
|
|
private Expression ReduceVariable() |
|
{ |
|
if (IsPrefix) |
|
{ |
|
// (op) var |
|
// ... is reduced into ... |
|
// var = op(var) |
|
return Assign(_operand, FunctionalOp(_operand)); |
|
} |
|
// var (op) |
|
// ... is reduced into ... |
|
// temp = var |
|
// var = op(var) |
|
// temp |
|
var temp = Parameter(_operand.Type, null); |
|
return Block( |
|
new[] { temp }, |
|
Assign(temp, _operand), |
|
Assign(_operand, FunctionalOp(temp)), |
|
temp |
|
); |
|
} |
|
|
|
private Expression ReduceMember() |
|
{ |
|
var member = (MemberExpression)_operand; |
|
if (member.Expression == null) |
|
{ |
|
//static member, reduce the same as variable |
|
return ReduceVariable(); |
|
} |
|
else |
|
{ |
|
var temp1 = Parameter(member.Expression.Type, null); |
|
var initTemp1 = Assign(temp1, member.Expression); |
|
member = MakeMemberAccess(temp1, member.Member); |
|
|
|
if (IsPrefix) |
|
{ |
|
// (op) value.member |
|
// ... is reduced into ... |
|
// temp1 = value |
|
// temp1.member = op(temp1.member) |
|
return Block( |
|
new[] { temp1 }, |
|
initTemp1, |
|
Assign(member, FunctionalOp(member)) |
|
); |
|
} |
|
|
|
// value.member (op) |
|
// ... is reduced into ... |
|
// temp1 = value |
|
// temp2 = temp1.member |
|
// temp1.member = op(temp2) |
|
// temp2 |
|
var temp2 = Parameter(member.Type, null); |
|
return Block( |
|
new[] { temp1, temp2 }, |
|
initTemp1, |
|
Assign(temp2, member), |
|
Assign(member, FunctionalOp(temp2)), |
|
temp2 |
|
); |
|
} |
|
} |
|
|
|
private Expression ReduceIndex() |
|
{ |
|
// left[a0, a1, ... aN] (op) |
|
// |
|
// ... is reduced into ... |
|
// |
|
// tempObj = left |
|
// tempArg0 = a0 |
|
// ... |
|
// tempArgN = aN |
|
// tempValue = tempObj[tempArg0, ... tempArgN] |
|
// tempObj[tempArg0, ... tempArgN] = op(tempValue) |
|
// tempValue |
|
|
|
var prefix = IsPrefix; |
|
var index = (IndexExpression)_operand; |
|
var count = index.Arguments.Count; |
|
var block = new Expression[count + (prefix ? 2 : 4)]; |
|
var temps = new ParameterExpression[count + (prefix ? 1 : 2)]; |
|
var args = new ParameterExpression[count]; |
|
|
|
var i = 0; |
|
temps[i] = Parameter(index.Object.Type, null); |
|
block[i] = Assign(temps[i], index.Object); |
|
i++; |
|
while (i <= count) |
|
{ |
|
var arg = index.Arguments[i - 1]; |
|
args[i - 1] = temps[i] = Parameter(arg.Type, null); |
|
block[i] = Assign(temps[i], arg); |
|
i++; |
|
} |
|
index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args)); |
|
if (!prefix) |
|
{ |
|
var lastTemp = temps[i] = Parameter(index.Type, null); |
|
block[i] = Assign(temps[i], index); |
|
i++; |
|
Debug.Assert(i == temps.Length); |
|
block[i++] = Assign(index, FunctionalOp(lastTemp)); |
|
block[i++] = lastTemp; |
|
} |
|
else |
|
{ |
|
Debug.Assert(i == temps.Length); |
|
block[i++] = Assign(index, FunctionalOp(index)); |
|
} |
|
Debug.Assert(i == block.Length); |
|
return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block)); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a new expression that is like this one, but using the |
|
/// supplied children. If all of the children are the same, it will |
|
/// return this expression. |
|
/// </summary> |
|
/// <param name="operand">The <see cref="Operand" /> property of the result.</param> |
|
/// <returns>This expression if no children changed, or an expression with the updated children.</returns> |
|
public UnaryExpression Update(Expression operand) |
|
{ |
|
if (operand == Operand) |
|
{ |
|
return this; |
|
} |
|
return MakeUnary(NodeType, operand, Type, Method); |
|
} |
|
} |
|
|
|
public partial class Expression |
|
{ |
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method. |
|
/// </summary> |
|
/// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param> |
|
/// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param> |
|
/// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param> |
|
/// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns> |
|
/// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception> |
|
public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) |
|
{ |
|
return MakeUnary(unaryType, operand, type, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method. |
|
/// </summary> |
|
/// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param> |
|
/// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param> |
|
/// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param> |
|
/// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param> |
|
/// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns> |
|
/// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception> |
|
public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) |
|
{ |
|
switch (unaryType) |
|
{ |
|
case ExpressionType.Negate: |
|
return Negate(operand, method); |
|
|
|
case ExpressionType.NegateChecked: |
|
return NegateChecked(operand, method); |
|
|
|
case ExpressionType.Not: |
|
return Not(operand, method); |
|
|
|
case ExpressionType.IsFalse: |
|
return IsFalse(operand, method); |
|
|
|
case ExpressionType.IsTrue: |
|
return IsTrue(operand, method); |
|
|
|
case ExpressionType.OnesComplement: |
|
return OnesComplement(operand, method); |
|
|
|
case ExpressionType.ArrayLength: |
|
return ArrayLength(operand); |
|
|
|
case ExpressionType.Convert: |
|
return Convert(operand, type, method); |
|
|
|
case ExpressionType.ConvertChecked: |
|
return ConvertChecked(operand, type, method); |
|
|
|
case ExpressionType.Throw: |
|
return Throw(operand, type); |
|
|
|
case ExpressionType.TypeAs: |
|
return TypeAs(operand, type); |
|
|
|
case ExpressionType.Quote: |
|
return Quote(operand); |
|
|
|
case ExpressionType.UnaryPlus: |
|
return UnaryPlus(operand, method); |
|
|
|
case ExpressionType.Unbox: |
|
return Unbox(operand, type); |
|
|
|
case ExpressionType.Increment: |
|
return Increment(operand, method); |
|
|
|
case ExpressionType.Decrement: |
|
return Decrement(operand, method); |
|
|
|
case ExpressionType.PreIncrementAssign: |
|
return PreIncrementAssign(operand, method); |
|
|
|
case ExpressionType.PostIncrementAssign: |
|
return PostIncrementAssign(operand, method); |
|
|
|
case ExpressionType.PreDecrementAssign: |
|
return PreDecrementAssign(operand, method); |
|
|
|
case ExpressionType.PostDecrementAssign: |
|
return PostDecrementAssign(operand, method); |
|
|
|
default: |
|
throw Error.UnhandledUnary(unaryType); |
|
} |
|
} |
|
|
|
private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) |
|
{ |
|
var u = GetUserDefinedUnaryOperator(unaryType, name, operand); |
|
if (u != null) |
|
{ |
|
ValidateParamswithOperandsOrThrow(u.Method.GetParameters()[0].ParameterType, operand.Type, unaryType, name); |
|
return u; |
|
} |
|
throw Error.UnaryOperatorNotDefined(unaryType, operand.Type); |
|
} |
|
|
|
private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) |
|
{ |
|
var operandType = operand.Type; |
|
var types = new[] { operandType }; |
|
var nnOperandType = operandType.GetNonNullableType(); |
|
var method = nnOperandType.GetStaticMethod(name, types); |
|
if (method != null) |
|
{ |
|
return new UnaryExpression(unaryType, operand, method.ReturnType, method); |
|
} |
|
// try lifted call |
|
if (operandType.IsNullableType()) |
|
{ |
|
types[0] = nnOperandType; |
|
method = nnOperandType.GetStaticMethod(name, types); |
|
if (method != null && method.ReturnType.IsValueType && !method.ReturnType.IsNullableType()) |
|
{ |
|
return new UnaryExpression(unaryType, operand, method.ReturnType.GetNullableType(), method); |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) |
|
{ |
|
Debug.Assert(method != null); |
|
ValidateOperator(method); |
|
var pms = method.GetParameters(); |
|
if (pms.Length != 1) |
|
{ |
|
throw Error.IncorrectNumberOfMethodCallArguments(method); |
|
} |
|
|
|
if (ParameterIsAssignable(pms[0], operand.Type)) |
|
{ |
|
ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name); |
|
return new UnaryExpression(unaryType, operand, method.ReturnType, method); |
|
} |
|
// check for lifted call |
|
if (operand.Type.IsNullableType() && |
|
ParameterIsAssignable(pms[0], operand.Type.GetNonNullableType()) && |
|
method.ReturnType.IsValueType && !method.ReturnType.IsNullableType()) |
|
{ |
|
return new UnaryExpression(unaryType, operand, method.ReturnType.GetNullableType(), method); |
|
} |
|
|
|
throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name); |
|
} |
|
|
|
private static UnaryExpression GetUserDefinedConversionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) |
|
{ |
|
var u = GetUserDefinedConversion(coercionType, expression, convertToType); |
|
if (u != null) |
|
{ |
|
return u; |
|
} |
|
throw Error.CoercionOperatorNotDefined(expression.Type, convertToType); |
|
} |
|
|
|
private static UnaryExpression GetUserDefinedConversion(ExpressionType coercionType, Expression expression, Type convertToType) |
|
{ |
|
var method = TypeHelper.GetUserDefinedConversionMethod(expression.Type, convertToType, false); |
|
if (method != null) |
|
{ |
|
return new UnaryExpression(coercionType, expression, convertToType, method); |
|
} |
|
else |
|
{ |
|
return null; |
|
} |
|
} |
|
|
|
private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) |
|
{ |
|
Debug.Assert(method != null); |
|
ValidateOperator(method); |
|
var pms = method.GetParameters(); |
|
if (pms.Length != 1) |
|
{ |
|
throw Error.IncorrectNumberOfMethodCallArguments(method); |
|
} |
|
if (ParameterIsAssignable(pms[0], operand.Type) && method.ReturnType == convertToType) |
|
{ |
|
return new UnaryExpression(unaryType, operand, method.ReturnType, method); |
|
} |
|
// check for lifted call |
|
if ((operand.Type.IsNullableType() || convertToType.IsNullableType()) && |
|
ParameterIsAssignable(pms[0], operand.Type.GetNonNullableType()) && |
|
method.ReturnType == convertToType.GetNonNullableType()) |
|
{ |
|
return new UnaryExpression(unaryType, operand, convertToType, method); |
|
} |
|
throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param> |
|
/// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> properties set to the specified value.</returns> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception> |
|
/// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception> |
|
public static UnaryExpression Negate(Expression expression) |
|
{ |
|
return Negate(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param> |
|
/// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param> |
|
/// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> and <see cref="P:UnaryExpression.Method"></see> properties set to the specified value.</returns> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception> |
|
/// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
/// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception> |
|
public static UnaryExpression Negate(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic() && !expression.Type.IsUnsignedInteger()) |
|
{ |
|
return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param> |
|
/// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> property set to the specified value.</returns> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception> |
|
/// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception> |
|
public static UnaryExpression UnaryPlus(Expression expression) |
|
{ |
|
return UnaryPlus(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param> |
|
/// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param> |
|
/// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> and <see cref="UnaryExpression.Method"></see>property set to the specified value.</returns> |
|
/// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception> |
|
/// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
/// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception> |
|
public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic()) |
|
{ |
|
return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method); |
|
} |
|
|
|
/// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
/// <exception cref="T:System.ArgumentNullException"> |
|
/// Thrown when <paramref name="expression" /> is null.</exception> |
|
/// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception> |
|
public static UnaryExpression NegateChecked(Expression expression) |
|
{ |
|
return NegateChecked(expression, null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> is null.</exception> |
|
///<exception cref="T:System.ArgumentException"> |
|
///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
///<exception cref="T:System.InvalidOperationException"> |
|
///<paramref name="method" /> is null and the unary minus operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception> |
|
public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic() && !expression.Type.IsUnsignedInteger()) |
|
{ |
|
return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> is null.</exception> |
|
///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception> |
|
public static UnaryExpression Not(Expression expression) |
|
{ |
|
return Not(expression, null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> is null.</exception> |
|
///<exception cref="T:System.ArgumentException"> |
|
///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
///<exception cref="T:System.InvalidOperationException"> |
|
///<paramref name="method" /> is null and the unary not operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception> |
|
public static UnaryExpression Not(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsIntegerOrBool()) |
|
{ |
|
return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null); |
|
} |
|
var u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression); |
|
if (u != null) |
|
{ |
|
return u; |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Returns whether the expression evaluates to false. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression IsFalse(Expression expression) |
|
{ |
|
return IsFalse(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Returns whether the expression evaluates to false. |
|
/// </summary> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression IsFalse(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsBool()) |
|
{ |
|
return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Returns whether the expression evaluates to true. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression IsTrue(Expression expression) |
|
{ |
|
return IsTrue(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Returns whether the expression evaluates to true. |
|
/// </summary> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to evaluate.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression IsTrue(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsBool()) |
|
{ |
|
return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Returns the expression representing the ones complement. |
|
/// </summary> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression OnesComplement(Expression expression) |
|
{ |
|
return OnesComplement(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Returns the expression representing the ones complement. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" />.</param> |
|
/// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsInteger()) |
|
{ |
|
return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.TypeAs" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> or <paramref name="type" /> is null.</exception> |
|
public static UnaryExpression TypeAs(Expression expression, Type type) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
ContractUtils.RequiresNotNull(type, "type"); |
|
TypeHelper.ValidateType(type); |
|
|
|
if (type.IsValueType && !type.IsNullableType()) |
|
{ |
|
throw Error.IncorrectTypeForTypeAs(type); |
|
} |
|
return new UnaryExpression(ExpressionType.TypeAs, expression, type, null); |
|
} |
|
|
|
/// <summary> |
|
/// <summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary> |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to unbox.</param> |
|
/// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param> |
|
/// <returns>An instance of <see cref="UnaryExpression"/>.</returns> |
|
public static UnaryExpression Unbox(Expression expression, Type type) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
ContractUtils.RequiresNotNull(type, "type"); |
|
if (!expression.Type.IsInterface && expression.Type != typeof(object)) |
|
{ |
|
throw Error.InvalidUnboxType(); |
|
} |
|
if (!type.IsValueType) |
|
{ |
|
throw Error.InvalidUnboxType(); |
|
} |
|
|
|
TypeHelper.ValidateType(type); |
|
return new UnaryExpression(ExpressionType.Unbox, expression, type, null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> or <paramref name="type" /> is null.</exception> |
|
///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception> |
|
public static UnaryExpression Convert(Expression expression, Type type) |
|
{ |
|
return Convert(expression, type, null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:System.Linq.Expressions.Expression.Type" />, and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> or <paramref name="type" /> is null.</exception> |
|
///<exception cref="T:System.ArgumentException"> |
|
///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception> |
|
///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception> |
|
public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
ContractUtils.RequiresNotNull(type, "type"); |
|
TypeHelper.ValidateType(type); |
|
|
|
if (method == null) |
|
{ |
|
if (TypeHelper.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) || |
|
TypeHelper.HasReferenceConversion(expression.Type, type)) |
|
{ |
|
return new UnaryExpression(ExpressionType.Convert, expression, type, null); |
|
} |
|
return GetUserDefinedConversionOrThrow(ExpressionType.Convert, expression, type); |
|
} |
|
return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> or <paramref name="type" /> is null.</exception> |
|
///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception> |
|
public static UnaryExpression ConvertChecked(Expression expression, Type type) |
|
{ |
|
return ConvertChecked(expression, type, null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed and for which the implementing method is specified.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:System.Linq.Expressions.Expression.Type" />, and <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:System.Linq.Expressions.Expression.Type" /> property equal to.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> or <paramref name="type" /> is null.</exception> |
|
///<exception cref="T:System.ArgumentException"> |
|
///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception> |
|
///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception> |
|
///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception> |
|
public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
ContractUtils.RequiresNotNull(type, "type"); |
|
TypeHelper.ValidateType(type); |
|
|
|
if (method == null) |
|
{ |
|
if (TypeHelper.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) |
|
{ |
|
return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null); |
|
} |
|
if (TypeHelper.HasReferenceConversion(expression.Type, type)) |
|
{ |
|
return new UnaryExpression(ExpressionType.Convert, expression, type, null); |
|
} |
|
return GetUserDefinedConversionOrThrow(ExpressionType.ConvertChecked, expression, type); |
|
} |
|
return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ArrayLength" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to <paramref name="array" />.</returns> |
|
///<param name="array">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="array" /> is null.</exception> |
|
///<exception cref="T:System.ArgumentException"> |
|
///<paramref name="array" />.Type does not represent an array type.</exception> |
|
public static UnaryExpression ArrayLength(Expression array) |
|
{ |
|
ContractUtils.RequiresNotNull(array, "array"); |
|
if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) |
|
{ |
|
throw Error.ArgumentMustBeArray(); |
|
} |
|
if (array.Type.GetArrayRank() != 1) |
|
{ |
|
throw Error.ArgumentMustBeSingleDimensionalArrayType(); |
|
} |
|
return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null); |
|
} |
|
|
|
///<summary>Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents an expression that has a constant value of type <see cref="T:System.Linq.Expressions.Expression" />.</summary> |
|
///<returns>A <see cref="T:System.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.Quote" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns> |
|
///<param name="expression">An <see cref="T:System.Linq.Expressions.Expression" /> to set the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param> |
|
///<exception cref="T:System.ArgumentNullException"> |
|
///<paramref name="expression" /> is null.</exception> |
|
public static UnaryExpression Quote(Expression expression) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
var validQuote = expression is LambdaExpression; |
|
if (!validQuote) |
|
{ |
|
throw Error.QuotedExpressionMustBeLambda(); |
|
} |
|
|
|
return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception. |
|
/// </summary> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns> |
|
public static UnaryExpression Rethrow() |
|
{ |
|
return Throw(null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type. |
|
/// </summary> |
|
///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns> |
|
public static UnaryExpression Rethrow(Type type) |
|
{ |
|
return Throw(null, type); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception. |
|
/// </summary> |
|
/// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns> |
|
public static UnaryExpression Throw(Expression value) |
|
{ |
|
return Throw(value, typeof(void)); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type. |
|
/// </summary> |
|
/// <param name="value">An <see cref="T:System.Linq.Expressions.Expression" />.</param> |
|
/// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns> |
|
public static UnaryExpression Throw(Expression value, Type type) |
|
{ |
|
ContractUtils.RequiresNotNull(type, "type"); |
|
TypeHelper.ValidateType(type); |
|
|
|
if (value != null) |
|
{ |
|
RequiresCanRead(value, "value"); |
|
if (value.Type.IsValueType) |
|
{ |
|
throw Error.ArgumentMustNotHaveValueType(); |
|
} |
|
} |
|
return new UnaryExpression(ExpressionType.Throw, value, type, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns> |
|
public static UnaryExpression Increment(Expression expression) |
|
{ |
|
return Increment(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to increment.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns> |
|
public static UnaryExpression Increment(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic()) |
|
{ |
|
return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns> |
|
public static UnaryExpression Decrement(Expression expression) |
|
{ |
|
return Decrement(expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="T:System.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to decrement.</param> |
|
///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns> |
|
public static UnaryExpression Decrement(Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic()) |
|
{ |
|
return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null); |
|
} |
|
return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression); |
|
} |
|
return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that increments the expression by 1 |
|
/// and assigns the result back to the expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PreIncrementAssign(Expression expression) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that increments the expression by 1 |
|
/// and assigns the result back to the expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1 |
|
/// and assigns the result back to the expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PreDecrementAssign(Expression expression) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1 |
|
/// and assigns the result back to the expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression |
|
/// followed by a subsequent increment by 1 of the original expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PostIncrementAssign(Expression expression) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression |
|
/// followed by a subsequent increment by 1 of the original expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression |
|
/// followed by a subsequent decrement by 1 of the original expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PostDecrementAssign(Expression expression) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null); |
|
} |
|
|
|
/// <summary> |
|
/// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression |
|
/// followed by a subsequent decrement by 1 of the original expression. |
|
/// </summary> |
|
/// <param name="expression">An <see cref="T:System.Linq.Expressions.Expression"></see> to apply the operations on.</param> |
|
/// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param> |
|
/// <returns>A <see cref="T:System.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns> |
|
public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) |
|
{ |
|
return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method); |
|
} |
|
|
|
private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) |
|
{ |
|
RequiresCanRead(expression, "expression"); |
|
RequiresCanWrite(expression, "expression"); |
|
|
|
UnaryExpression result; |
|
if (method == null) |
|
{ |
|
if (expression.Type.IsArithmetic()) |
|
{ |
|
return new UnaryExpression(kind, expression, expression.Type, null); |
|
} |
|
string name; |
|
if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) |
|
{ |
|
name = "op_Increment"; |
|
} |
|
else |
|
{ |
|
name = "op_Decrement"; |
|
} |
|
result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression); |
|
} |
|
else |
|
{ |
|
result = GetMethodBasedUnaryOperator(kind, expression, method); |
|
} |
|
// return type must be assignable back to the operand type |
|
if (!TypeHelper.AreReferenceAssignable(expression.Type, result.Type)) |
|
{ |
|
throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name); |
|
} |
|
return result; |
|
} |
|
} |
|
} |
|
|
|
#endif |