Open sandboxFocusImprove this doc

LAMA0528: An existing member must be public to implement an interface member

Severity Error
Reported by Metalama.Framework
Message The aspect '<AspectType>' cannot override the member '<Member>' to implement an interface member because '<Member>' is not public. Make '<Member>' public, or implement the interface member explicitly.

Cause

When an aspect implements an interface with the ImplementInterface method, it provides each interface member with a template marked with [InterfaceMember]. By default, Metalama creates an implicit implementation, that is, a public member of the target type.

If the target type already has a method, property, or event with the same name and signature as the interface member, and the aspect passes OverrideStrategy.Override as the whenExists argument, Metalama doesn't introduce a new member. Instead, it overrides the existing member with the template, and this member becomes the implementation of the interface member. An implicit interface implementation must be public, so Metalama reports LAMA0528 when the existing member is private, protected, or internal. In the message, <Member> is the existing member of the target type.

In the following example, the Disposable aspect implements IDisposable, but the Dispose method of the target class is private because it has no access modifier.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0528.Error;
6
7public class DisposableAttribute : TypeAspect
8{
9    public override void BuildAspect( IAspectBuilder<INamedType> builder )
10    {
11        // If the type already has a Dispose method, override it.
12        builder.ImplementInterface( typeof(IDisposable), whenExists: OverrideStrategy.Override );
13    }
14
15    [InterfaceMember]
16    public void Dispose()
17    {
18        meta.Proceed();
19        Console.WriteLine( $"{meta.Target.Type.Name} disposed." );
20    }
21}
22
1using System;
2
3namespace Doc.LAMA0528.Error;
4
5[Disposable]
Error LAMA0528: The aspect 'Disposable' cannot override the member 'FileLogger.Dispose()' to implement an interface member because 'FileLogger.Dispose()' is not public. Make 'FileLogger.Dispose()' public, or implement the interface member explicitly.

6internal partial class FileLogger
7{
8    // Error: this method is private because it has no access modifier, so it can't implement IDisposable.Dispose.
9    void Dispose()
10    {
11        Console.WriteLine( "Closing the log file." );
12    }
13}
14

Resolution

Do one of the following:

  • Make the existing member public, so that Metalama can override it and use it as the implementation of the interface member. The following example shows this fix.
  • If the existing member must stay non-public, set the IsExplicit property of the [InterfaceMember] attribute to true. Metalama then introduces an explicit interface implementation and leaves the existing member unchanged.
  • Rename the existing member if it isn't meant to implement the interface.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0528.Fixed;
6
7public class DisposableAttribute : TypeAspect
8{
9    public override void BuildAspect( IAspectBuilder<INamedType> builder )
10    {
11        // If the type already has a Dispose method, override it.
12        builder.ImplementInterface( typeof(IDisposable), whenExists: OverrideStrategy.Override );
13    }
14
15    [InterfaceMember]
16    public void Dispose()
17    {
18        meta.Proceed();
19        Console.WriteLine( $"{meta.Target.Type.Name} disposed." );
20    }
21}
22
Source Code
1using System;
2
3namespace Doc.LAMA0528.Fixed;
4
5[Disposable]
6internal partial class FileLogger
7{
8    // Fixed: the method is public, so the aspect can override it to implement IDisposable.Dispose.
9    public void Dispose()
10    {
11        Console.WriteLine( "Closing the log file." );
12    }
13}

14
Transformed Code
1using System;
2
3namespace Doc.LAMA0528.Fixed;
4
5[Disposable]
6internal partial class FileLogger : IDisposable
7{
8    // Fixed: the method is public, so the aspect can override it to implement IDisposable.Dispose.
9    public void Dispose()
10    {
11        Console.WriteLine("Closing the log file.");
12        Console.WriteLine("FileLogger disposed.");
13    }
14}
15

See also