| Severity | Warning |
| Reported by | Metalama.Extensions.Architecture |
| Message | The '<ValidatedDeclaration>' <ValidatedDeclarationKind> cannot be <UsageKind> by the '<ReferencingDeclaration>' <ReferencingDeclarationKind>.<OptionalSpace><Description> |
Cause
Metalama.Extensions.Architecture lets you restrict the code that can use a type, a member, or a namespace. You define these rules with attributes such as CanOnlyBeUsedFromAttribute, CannotBeUsedFromAttribute, InternalsCanOnlyBeUsedFromAttribute, and InternalsCannotBeUsedFromAttribute, or with the CanOnlyBeUsedFrom and CannotBeUsedFrom methods in a fabric.
Metalama reports LAMA0905 on each reference to a constrained declaration from code that the rule doesn't allow. References from within the constrained type itself are never reported. A var local variable whose inferred type is the constrained type also counts as a reference. The message contains the following parts:
<ValidatedDeclaration>and<ValidatedDeclarationKind>are the referenced declaration and its kind, for example'Order' type.<UsageKind>isassignedfor an assignment andreferencedfor any other kind of reference.<ReferencingDeclaration>and<ReferencingDeclarationKind>are the referencing declaration and its kind. Depending on the rule, it's a type or a namespace.<OptionalSpace><Description>is the text of the rule's Description property, if any.
In the following example, the Order class can only be used from OrderFactory, but OrderController instantiates it directly.
1using Metalama.Extensions.Architecture.Aspects;
2using System;
3
4namespace Doc.LAMA0905.Error;
5
6[CanOnlyBeUsedFrom( Types = [typeof( OrderFactory )], Description = "Use OrderFactory to create orders." )]
7public class Order
8{
9 public decimal Amount { get; set; }
10}
11
12public class OrderFactory
13{
14 public Order Create( decimal amount ) => new Order { Amount = amount };
15}
16
17public class OrderController
18{
19 public void Submit( decimal amount )
20 {
21 // OrderController is not allowed to use the Order class.
Warning LAMA0905: The 'Order' type cannot be referenced by the 'OrderController' type. Use OrderFactory to create orders.
22 Console.WriteLine( new Order() );
23 }
24}
25
Resolution
Depending on your intent, do one of the following:
- Change the referencing code so that it respects the rule, typically by going through the API that the rule allows. The description in the message often says which one.
- If the referencing code is legitimately allowed to use the declaration, extend the scope of the rule, for instance by adding the type or namespace to the Types or Namespaces property, or define an exclusion with the ExclusionPredicateType property.
- To accept a single violation, suppress the warning with
#pragma warning disable LAMA0905.
In the following example, OrderController creates the order through OrderFactory.
1using Metalama.Extensions.Architecture.Aspects;
2using System;
3
4namespace Doc.LAMA0905.Fixed;
5
6[CanOnlyBeUsedFrom( Types = [typeof( OrderFactory )], Description = "Use OrderFactory to create orders." )]
7public class Order
8{
9 public decimal Amount { get; set; }
10}
11
12public class OrderFactory
13{
14 public Order Create( decimal amount ) => new Order { Amount = amount };
15}
16
17public class OrderController
18{
19 public void Submit( decimal amount )
20 {
21 // OrderController uses the factory instead of the Order class.
22 Console.WriteLine( new OrderFactory().Create( amount ) );
23 }
24}
25