Open sandboxFocusImprove this doc

PS0136: Unmatched or Empty Curly Bracket in an Expression

Severity Error
Reported by PostSharp
Message Invalid expression "<Expression>": the bracket at position <Position> has no matching bracket or encloses no expression.

Cause

Many attributes of a postsharp.config file, such as the Value of a Property element, the File of a Using element or the Condition of most elements, accept expressions. PostSharp evaluates each substring between curly brackets, such as {$AssemblyName}, as an XPath expression, and copies the rest of the attribute as it is. See Using Expressions in Configuration Files.

PostSharp reports PS0136 when the attribute has:

  • an opening curly bracket { with no closing } after it;
  • a closing curly bracket } with no opening { before it;
  • a pair of curly brackets with nothing but white space between them, such as {}.

<Expression> is the whole value of the attribute, and <Position> is the position of the bracket in it, starting at 1: the opening bracket of an unclosed or empty pair, or the lone closing bracket. The location of the message is the element of the configuration file. PostSharp does not evaluate the attribute. Because the configuration of the project has an error, PostSharp then stops with PS0084.

In the following example, the TraceCategory property of postsharp.config refers to the AssemblyName property, but the closing bracket is missing.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
  <!-- The expression {$AssemblyName is not closed by a curly bracket. -->
  <Property Name="TraceCategory" Value="Orders.{$AssemblyName" />
</Project>
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.PS0136_Error;

// The postsharp.config file of this folder defines the TraceCategory property with an expression that is not closed.

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}." );
    }
}

public class OrderService
{
    [Log]
    public void PlaceOrder( string product )
    {
        Console.WriteLine( $"Order placed for {product}." );
    }
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Coffee" );
    }
}
error PS0084: The project could not be initialized because of the previous errors.
error PS0136: postsharp.config(4,4): Invalid expression "Orders.{$AssemblyName": the bracket at position 8 has no matching bracket or encloses no expression.

Resolution

  • Add the missing bracket, or remove the stray one.
  • Write an expression between the brackets of an empty pair, or remove the pair.
  • When the attribute must contain a literal curly bracket, double it: PostSharp reads {{ as { and }} as }.

In the following example, the expression is closed.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
  <!-- The expression {$AssemblyName} is closed. -->
  <Property Name="TraceCategory" Value="Orders.{$AssemblyName}" />
</Project>
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace Errors.PS0136_Fixed;

// The postsharp.config file of this folder defines the TraceCategory property with a closed expression.

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}." );
    }
}

public class OrderService
{
    [Log]
    public void PlaceOrder( string product )
    {
        Console.WriteLine( $"Order placed for {product}." );
    }
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Coffee" );
    }
}
Entering PlaceOrder.
Order placed for Coffee.

See Also

Other Resources

Using Expressions in Configuration Files
Configuration File Schema Reference
Configuring Projects Using postsharp.config