| Severity | Error |
| Reported by | Metalama.Extensions.DependencyInjection |
| Message | The dependency '<DependencyType>' cannot be pulled from the constructor '<Constructor>' because '<DependencyType>' has lower accessibility than the constructor. |
Cause
With the default .NET Core pattern, implemented by DefaultDependencyInjectionFramework, a dependency is pulled from the constructors of the target type: Metalama adds a parameter of the dependency type to each constructor and assigns it to the dependency field or property. C# doesn't allow a parameter type to be less accessible than its method, so the parameter can't be added when the dependency type is less accessible than the constructor.
Metalama reports LAMA0704 when the effective accessibility of the dependency type is lower than the effective accessibility of the constructor. Effective accessibility takes the containing types into account: a public constructor of an internal class is effectively internal. In the message, <DependencyType> is the dependency type and <Constructor> is the constructor. When the target type has no explicit constructor, the diagnostic is reported on the type.
In the following example, the Audit aspect introduces an IAuditSink dependency, but IAuditSink is internal while OrderService and its implicit constructor are public.
1using Metalama.Extensions.DependencyInjection;
2using Metalama.Framework.Aspects;
3
4namespace Doc.LAMA0704.Error;
5
6public class AuditAttribute : TypeAspect
7{
8 [IntroduceDependency]
9 private readonly IAuditSink _auditSink;
10}
11
1namespace Doc.LAMA0704.Error;
2
3// The dependency type is internal.
4internal interface IAuditSink
5{
6 void Write( string message );
7}
8
9// Error: the public constructor of OrderService can't receive an internal IAuditSink.
10[Audit]
Error LAMA0704: The dependency 'IAuditSink' cannot be pulled from the constructor 'OrderService.OrderService()' because 'IAuditSink' has lower accessibility than the constructor.
11public partial class OrderService
12{
13 public void PlaceOrder() { }
14}
15
Resolution
Make the accessibility of the dependency type and of the constructor consistent:
- Make the dependency type at least as accessible as the constructor, as in the following example.
- Reduce the accessibility of the target type or of its constructors, for instance by making the class
internal.
1using Metalama.Extensions.DependencyInjection;
2using Metalama.Framework.Aspects;
3
4namespace Doc.LAMA0704.Fixed;
5
6public class AuditAttribute : TypeAspect
7{
8 [IntroduceDependency]
9 private readonly IAuditSink _auditSink;
10}
11
1namespace Doc.LAMA0704.Fixed;
2
3// Fixed: the dependency type is public, like the constructor that receives it.
4public interface IAuditSink
5{
6 void Write( string message );
7}
8
9[Audit]
10public partial class OrderService
11{
12 public void PlaceOrder() { }
13}
14
1using Metalama.Framework.RunTime;
2
3namespace Doc.LAMA0704.Fixed;
4
5// Fixed: the dependency type is public, like the constructor that receives it.
6public interface IAuditSink
7{
8 void Write(string message);
9}
10
11[Audit]
12public partial class OrderService
13{
14 public void PlaceOrder() { }
15
16 private IAuditSink _auditSink;
17
18 public OrderService([AspectGenerated] IAuditSink? auditSink = null)
19 {
20 this._auditSink = auditSink ?? throw new System.ArgumentNullException(nameof(auditSink));
21 }
22}
23