Open sandboxFocus

Class ContractAspect

A base aspect that can validate or change the value of fields, properties, indexers, and parameters. Contracts are typically used to validate input parameters (preconditions), output parameters and return values (postconditions), or to normalize values. For ready-made contract implementations, see the Metalama.Patterns.Contracts package.

Inheritance
ContractAspect
Namespace: Metalama.Framework.Aspects
Assembly: Metalama.Framework.dll
Syntax
[AttributeUsage(AttributeTargets.Property|AttributeTargets.Field|AttributeTargets.Parameter|AttributeTargets.ReturnValue)]
[Layers(new string[] { "Build" })]
[Inheritable]
public abstract class ContractAspect : Aspect, IAspect<IParameter>, IEligible<IParameter>, IAspect<IFieldOrPropertyOrIndexer>, IAspect, ICompileTimeSerializable, ITemplateProvider, IEligible<IFieldOrPropertyOrIndexer>
Remarks

Contract Directions: A contract aspect can apply to the input data flow, output data flow, or both, according to the ContractDirection value returned by GetDefinedDirection(IAspectBuilder). The default direction is:

  • For input and ref parameters: the input value (precondition).
  • For fields and properties: the assigned value (i.e., the value parameter of the setter).
  • For out parameters and return value parameters: the output value (postcondition).

To customize the contract direction, override the GetDefinedDirection(IAspectBuilder) method in your derived contract aspect class.

Accessing Metadata: In your Validate(dynamic?) template, you can access the target context using:

  • meta.Target.Expression - Returns the target field, property, or parameter as a unified IExpression.
  • meta.Target.FieldOrProperty - Returns the target property or field (throws if applied to a parameter).
  • meta.Target.Parameter - Returns the target parameter (throws if applied to a field or property).
  • meta.Target.ContractDirection - Returns Input or Output according to the data flow being validated.

Eligibility: Since the current class does not know the value of the contract direction before it is instantiated, this class cannot set the eligibility conditions using the BuildEligibility(IEligibilityBuilder<IFieldOrPropertyOrIndexer>) method. If a derived class targets a specific ContractDirection (i.e. if the choice is not left to the user), its implementation of BuildEligibility(IEligibilityBuilder<IFieldOrPropertyOrIndexer>) can call BuildEligibilityForDirection(IEligibilityBuilder<IFieldOrPropertyOrIndexer>, ContractDirection) methods. This means that eligibility can be checked upfront by the IDE before suggesting the code actions.

In any case, this aspect verifies the eligibility of the target with respect to the specific ContractDirection and target declaration. This verification cannot be skipped.

Programmatic Usage: You can add contracts programmatically using AddContract(IAdviser<IFieldOrPropertyOrIndexer>, string, ContractDirection, object?, object?) from your aspect's BuildAspect method. When possible, provide all contracts to the same method from a single aspect for better compile-time performance.

Ready-Made Contracts: Instead of implementing your own contract aspects, consider using the ready-made contracts provided by the Metalama.Patterns.Contracts package, which includes contracts for nullability ([NotNull], [Required]), strings ([Email], [Url], [Phone], [CreditCard], [StringLength]), numeric ranges ([Range], [Positive], [Negative]), enums ([EnumDataType]), and collections ([NotEmpty]). See Metalama.Patterns.ContractsMetalama.Patterns.Contracts for details.

Constructors

Name Description
ContractAspect()
ContractAspect(ContractDirection)

Initializes a new instance of the ContractAspect class.

Fields

Name Description
BuildLayer

Methods

Name Description
BuildAspect(IAspectBuilder<IFieldOrPropertyOrIndexer>)
BuildAspect(IAspectBuilder<IParameter>)
BuildEligibility(IEligibilityBuilder<IFieldOrPropertyOrIndexer>)

Configures the eligibility of the aspect or attribute by defining rules that determine which declarations the aspect can be applied to.

BuildEligibility(IEligibilityBuilder<IParameter>)

Configures the eligibility of the aspect or attribute by defining rules that determine which declarations the aspect can be applied to.

BuildEligibilityForDirection(IEligibilityBuilder<IFieldOrPropertyOrIndexer>, ContractDirection)

Populates the IEligibilityBuilder for a field, property or indexer when the ContractDirection is known.

BuildEligibilityForDirection(IEligibilityBuilder<IParameter>, ContractDirection)

Populates the IEligibilityBuilder for a parameter when the ContractDirection is known.

GetActualDirection(IAspectBuilder, ContractDirection)

Gets the actual direction of the contract given the direction returned by GetDefinedDirection(IAspectBuilder), after resolving the Default value according to the characteristics of the target declaration, and after taking predecessors and secondary instances into account. The implementation of this method may return None to skip the aspect.

GetDefinedDirection(IAspectBuilder)

Gets or sets the direction of the data flow (Input, Output or Both) to which this contract applies, as defined by the current aspect. This method returns Default by default. When this method returns Default, the actual direction is determined according to the characteristics of the target declaration.

RedirectContracts(IAspectBuilder, IFieldOrPropertyOrIndexer, IParameter)

Redirects validation logic of ContractAspect from the specified property to the specified parameter.

Validate(dynamic?)

The template method that validates or normalizes the value of a field, property, indexer, or parameter.

Extension Methods

See Also