Open sandboxFocusImprove this doc

LAMA0257: A template member can't be set from an attribute

Severity Error
Reported by Metalama.Framework
Message The template member '<Member>' cannot be set from an aspect custom attribute. Add a separate aspect property that is not a template and set this property instead.

Cause

The members of an aspect class have two different roles. Regular fields and properties configure the aspect: you can set them from the custom attribute, and templates read their compile-time value. Members marked with a template attribute, such as [IntroduceAttribute] or [TemplateAttribute], are templates: they describe code that Metalama adds to the target, and their value is never available to the aspect.

Metalama reports LAMA0257 when a custom attribute that applies an aspect uses a named argument to set a template member.

In the following example, the Category property of the Trackable aspect is marked with [IntroduceAttribute], so it's a template. The attribute that applies the aspect to Order tries to set it with a named argument.

1using Metalama.Framework.Aspects;
2
3namespace Doc.LAMA0257.Error;
4
5public class TrackableAttribute : TypeAspect
6{
7    // This property is a template: it describes a property that the aspect introduces into the target type.
8    [Introduce]
9    public string Category { get; set; } = "General";
10}
11
1namespace Doc.LAMA0257.Error;
2
3// Error: the Category property of the aspect is a template and can't be set from the attribute.
Error LAMA0257: The template member 'Category' cannot be set from an aspect custom attribute. Add a separate aspect property that is not a template and set this property instead.

4[Trackable( Category = "Orders" )]
5internal partial class Order
6{
7    public int Id { get; set; }
8}
9

Resolution

Separate the configuration from the introduced member:

  1. Add a regular property, without a template attribute, to configure the aspect, and set this property from the custom attribute.
  2. Read this property from the template of the introduced member, for instance in the expression body of an introduced property. Metalama replaces the reference with the compile-time value.

If you need more control, introduce the member programmatically from BuildAspect and pass the value as a template argument.

In the following example, the aspect has a regular CategoryName property, which the attribute sets, and the introduced Category property reads it.

1using Metalama.Framework.Aspects;
2
3namespace Doc.LAMA0257.Fixed;
4
5public class TrackableAttribute : TypeAspect
6{
7    // This property configures the aspect. It is not a template, so the attribute can set it.
8    public string CategoryName { get; set; } = "General";
9
10    // This template reads the configuration to compute the introduced property.
11    [Introduce]
12    public string Category => this.CategoryName;
13}
14
Source Code
1namespace Doc.LAMA0257.Fixed;
2
3// Fixed: the attribute sets CategoryName, a regular property of the aspect.
4[Trackable( CategoryName = "Orders" )]

5internal partial class Order
6{
7    public int Id { get; set; }
8}
9
Transformed Code
1namespace Doc.LAMA0257.Fixed;
2
3// Fixed: the attribute sets CategoryName, a regular property of the aspect.
4[Trackable(CategoryName = "Orders")]
5internal partial class Order
6{
7    public int Id { get; set; }
8
9    public string Category
10    {
11        get
12        {
13            return "Orders";
14        }
15    }
16}
17

See also