Open sandboxFocusImprove this doc

PS0202: No Constructor Matches the Arguments of an ObjectConstruction

Severity Error
Reported by PostSharp
Message Invalid ObjectConstruction: cannot find a suitable constructor in type '<AspectType>' for arguments (<ArgumentTypes>).

Cause

An aspect that implements IAspectProvider can add aspects to other declarations, as Adding Aspects Programmatically Using IAspectProvider describes. Instead of an aspect object, the AspectInstance that it returns can hold an ObjectConstruction: the type of the aspect, the arguments of its constructor and the values of its properties, from which PostSharp builds the aspect as it would build a custom attribute.

PostSharp reports PS0202 when no constructor of the aspect class accepts the arguments of the ObjectConstruction: their number differs, an argument has a type that the parameter does not accept, or an argument is null for a parameter of a value type. <AspectType> is the assembly-qualified name of the aspect class, and <ArgumentTypes> lists the types of the arguments, empty when there is none. PS0202 has no location; PostSharp also reports LA0117, which names the aspect provider and the target declaration.

In the following example, the aspect provider creates a LogAttribute without arguments, but its only constructor takes a category.

using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Reflection;
using PostSharp.Serialization;
using BindingFlags = System.Reflection.BindingFlags;

namespace Errors.PS0202_Error;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public LogAttribute( string category )
    {
        this.Category = category;
    }

    public string Category { get; set; }

    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"[{this.Category}] Entering {args.Method.Name}." );
}

// Adds a LogAttribute to the public methods of the target class.
[PSerializable]
public class LogPublicMethodsAttribute : TypeLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        Type type = (Type) targetElement;

        foreach ( MethodInfo method in type.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly ) )
        {
            // LogAttribute has no parameterless constructor: the category is missing.
            ObjectConstruction construction = new( typeof(LogAttribute) );

            yield return new AspectInstance( method, construction );
        }
    }
}

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

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Chair" );
    }
}
error LA0117: PS0202_Error.cs(26,14): Cannot parse the ObjectConstruction provided by the aspect provider "Errors.PS0202_Error.LogPublicMethodsAttribute" applied on "Errors.PS0202_Error.OrderService.PlaceOrder(System.String)".
error PS0202: Invalid ObjectConstruction: cannot find a suitable constructor in type 'Errors.PS0202_Error.LogAttribute, PS0202_Error, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' for arguments ().

Resolution

Pass to the ObjectConstruction the arguments of one of the constructors of the aspect class, in the order and with the types of its parameters. Set the other values with the NamedArguments of the object construction. Alternatively, create the aspect object yourself and pass it to the AspectInstance constructor.

In the following example, the aspect provider passes the name of the class as the category.

using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Reflection;
using PostSharp.Serialization;
using BindingFlags = System.Reflection.BindingFlags;

namespace Errors.PS0202_Fixed;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public LogAttribute( string category )
    {
        this.Category = category;
    }

    public string Category { get; set; }

    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"[{this.Category}] Entering {args.Method.Name}." );
}

// Adds a LogAttribute to the public methods of the target class.
[PSerializable]
public class LogPublicMethodsAttribute : TypeLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        Type type = (Type) targetElement;

        foreach ( MethodInfo method in type.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly ) )
        {
            // The category matches the constructor of LogAttribute.
            ObjectConstruction construction = new( typeof(LogAttribute), type.Name );

            yield return new AspectInstance( method, construction );
        }
    }
}

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

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

See Also

Reference

ObjectConstruction
AspectInstance
IAspectProvider

Other Resources

Adding Aspects Programmatically Using IAspectProvider