| 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:
- Add a regular property, without a template attribute, to configure the aspect, and set this property from the custom attribute.
- 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
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
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