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.
177 lines
7.8 KiB
177 lines
7.8 KiB
5 years ago
|
#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;
|
||
|
|
||
|
namespace System.Linq.Expressions.Reimplement
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Represents a catch statement in a try block.
|
||
|
/// This must have the same return type (i.e., the type of <see cref="P:CatchBlock.Body"/>) as the try block it is associated with.
|
||
|
/// </summary>
|
||
|
[DebuggerTypeProxy(typeof(CatchBlockProxy))]
|
||
|
public sealed class CatchBlock
|
||
|
{
|
||
|
private readonly Type _test;
|
||
|
private readonly ParameterExpression _var;
|
||
|
private readonly Expression _body;
|
||
|
private readonly Expression _filter;
|
||
|
|
||
|
internal CatchBlock(Type test, ParameterExpression variable, Expression body, Expression filter)
|
||
|
{
|
||
|
_test = test;
|
||
|
_var = variable;
|
||
|
_body = body;
|
||
|
_filter = filter;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets a reference to the <see cref="Exception"/> object caught by this handler.
|
||
|
/// </summary>
|
||
|
public ParameterExpression Variable
|
||
|
{
|
||
|
get { return _var; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the type of <see cref="Exception"/> this handler catches.
|
||
|
/// </summary>
|
||
|
public Type Test
|
||
|
{
|
||
|
get { return _test; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the body of the catch block.
|
||
|
/// </summary>
|
||
|
public Expression Body
|
||
|
{
|
||
|
get { return _body; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the body of the <see cref="CatchBlock"/>'s filter.
|
||
|
/// </summary>
|
||
|
public Expression Filter
|
||
|
{
|
||
|
get { return _filter; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns a <see cref="string"/> that represents the current <see cref="object"/>.
|
||
|
/// </summary>
|
||
|
/// <returns>A <see cref="string"/> that represents the current <see cref="object"/>. </returns>
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return ExpressionStringBuilder.CatchBlockToString(this);
|
||
|
}
|
||
|
|
||
|
/// <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="variable">The <see cref="Variable" /> property of the result.</param>
|
||
|
/// <param name="filter">The <see cref="Filter" /> property of the result.</param>
|
||
|
/// <param name="body">The <see cref="Body" /> property of the result.</param>
|
||
|
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
|
||
|
public CatchBlock Update(ParameterExpression variable, Expression filter, Expression body)
|
||
|
{
|
||
|
if (variable == Variable && filter == Filter && body == Body)
|
||
|
{
|
||
|
return this;
|
||
|
}
|
||
|
return Expression.MakeCatchBlock(Test, variable, body, filter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public partial class Expression
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Creates a <see cref="CatchBlock"/> representing a catch statement.
|
||
|
/// The <see cref="Type"/> of object to be caught can be specified but no reference to the object
|
||
|
/// will be available for use in the <see cref="CatchBlock"/>.
|
||
|
/// </summary>
|
||
|
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
|
||
|
/// <param name="body">The body of the catch statement.</param>
|
||
|
/// <returns>The created <see cref="CatchBlock"/>.</returns>
|
||
|
public static CatchBlock Catch(Type type, Expression body)
|
||
|
{
|
||
|
return MakeCatchBlock(type, null, body, null);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a <see cref="CatchBlock"/> representing a catch statement with a reference to the caught object for use in the handler body.
|
||
|
/// </summary>
|
||
|
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
|
||
|
/// <param name="body">The body of the catch statement.</param>
|
||
|
/// <returns>The created <see cref="CatchBlock"/>.</returns>
|
||
|
public static CatchBlock Catch(ParameterExpression variable, Expression body)
|
||
|
{
|
||
|
ContractUtils.RequiresNotNull(variable, "variable");
|
||
|
return MakeCatchBlock(variable.Type, variable, body, null);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a <see cref="CatchBlock"/> representing a catch statement with
|
||
|
/// an <see cref="Exception"/> filter but no reference to the caught <see cref="Exception"/> object.
|
||
|
/// </summary>
|
||
|
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
|
||
|
/// <param name="body">The body of the catch statement.</param>
|
||
|
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
|
||
|
/// <returns>The created <see cref="CatchBlock"/>.</returns>
|
||
|
public static CatchBlock Catch(Type type, Expression body, Expression filter)
|
||
|
{
|
||
|
return MakeCatchBlock(type, null, body, filter);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a <see cref="CatchBlock"/> representing a catch statement with
|
||
|
/// an <see cref="Exception"/> filter and a reference to the caught <see cref="Exception"/> object.
|
||
|
/// </summary>
|
||
|
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
|
||
|
/// <param name="body">The body of the catch statement.</param>
|
||
|
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
|
||
|
/// <returns>The created <see cref="CatchBlock"/>.</returns>
|
||
|
public static CatchBlock Catch(ParameterExpression variable, Expression body, Expression filter)
|
||
|
{
|
||
|
ContractUtils.RequiresNotNull(variable, "variable");
|
||
|
return MakeCatchBlock(variable.Type, variable, body, filter);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements.
|
||
|
/// </summary>
|
||
|
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
|
||
|
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
|
||
|
/// <param name="body">The body of the catch statement.</param>
|
||
|
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
|
||
|
/// <returns>The created <see cref="CatchBlock"/>.</returns>
|
||
|
/// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks>
|
||
|
public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter)
|
||
|
{
|
||
|
ContractUtils.RequiresNotNull(type, "type");
|
||
|
ContractUtils.Requires(variable == null || variable.Type == type, "variable");
|
||
|
if (variable != null && variable.IsByRef)
|
||
|
{
|
||
|
throw Error.VariableMustNotBeByRef(variable, variable.Type);
|
||
|
}
|
||
|
RequiresCanRead(body, "body");
|
||
|
if (filter != null)
|
||
|
{
|
||
|
RequiresCanRead(filter, "filter");
|
||
|
if (filter.Type != typeof(bool))
|
||
|
{
|
||
|
throw Error.ArgumentMustBeBoolean();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new CatchBlock(type, variable, body, filter);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|