Open sandboxFocusImprove this doc

LAMA0020: The type can't be found

Severity Error
Reported by Metalama.Framework
Message Cannot find the type '<TypeName>'<AssemblyClause> in the project or its references. Use the reflection name of the type: separate nested types with '+', and write generic types with a backtick followed by the number of type parameters, for example 'System.Collections.Generic.List`1'.

Cause

Metalama reports LAMA0020 when compile-time code, such as a template or a BuildAspect method, asks for a type that doesn't exist in the compilation of the target project or in its references. In the message, <TypeName> is the requested type name, and <AssemblyClause> names the assembly expected to contain it, for instance of assembly 'MyLibrary'. When the type is requested by name only, the assembly is unknown and the message doesn't mention one.

The most common causes are:

  • You pass a type name to GetType, but the name isn't a valid reflection name. Reflection names differ from C# names: nested types are separated from their parent with +, and generic types are written with a backtick and the number of type parameters, without type arguments.
  • The type name is misspelled, or it lacks its namespace.
  • The type exists in the assembly that compiled your aspect, but not in the version of this assembly referenced by the target project.

In the following example, the Log aspect looks up the nested Logging.ConsoleLogger class using a . instead of a +.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System.Linq;
4
5namespace Doc.LAMA0020.Error;
6
7public class LogAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        // Error: a nested type must be separated from its parent type with '+', not '.'.
12        var loggerType = TypeFactory.GetType( "Doc.LAMA0020.Error.Logging.ConsoleLogger" );
13
14        loggerType.Methods.OfName( "Write" ).Single().Invoke( $"Executing {meta.Target.Method}." );
15
16        return meta.Proceed();
17    }
18}
19
1using System;
2
3namespace Doc.LAMA0020.Error;
4
5internal static class Logging
6{
7    public static class ConsoleLogger
8    {
9        public static void Write( string message ) => Console.WriteLine( message );
10    }
11}
12
13internal class Calculator
14{
15    [Log]
    Error LAMA0020: Cannot find the type 'Doc.LAMA0020.Error.Logging.ConsoleLogger' in the project or its references. Use the reflection name of the type: separate nested types with '+', and write generic types with a backtick followed by the number of type parameters, for example 'System.Collections.Generic.List`1'.

16    public int Add( int a, int b ) => a + b;
17}
18

Resolution

  • Pass the reflection name of the type, as in the following example. To check a name, look at the value of typeof(T).FullName.
  • When the type is known when you write the aspect, prefer passing typeof(T) to TypeFactory.GetType instead of a string.
  • If the type is optional, use TypeFactory.TryGetType and handle the case where the type doesn't exist.
  • If the type comes from a package, make sure that the target project references a version of the package that contains the type.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System.Linq;
4
5namespace Doc.LAMA0020.Fixed;
6
7public class LogAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        // Fixed: the reflection name of a nested type uses '+' as the separator.
12        var loggerType = TypeFactory.GetType( "Doc.LAMA0020.Fixed.Logging+ConsoleLogger" );
13
14        loggerType.Methods.OfName( "Write" ).Single().Invoke( $"Executing {meta.Target.Method}." );
15
16        return meta.Proceed();
17    }
18}
19
Source Code
1using System;
2
3namespace Doc.LAMA0020.Fixed;
4
5internal static class Logging
6{
7    public static class ConsoleLogger
8    {
9        public static void Write( string message ) => Console.WriteLine( message );
10    }
11}
12
13internal class Calculator
14{
15    [Log]
16    public int Add( int a, int b ) => a + b;
17}
18
Transformed Code
1using System;
2
3namespace Doc.LAMA0020.Fixed;
4
5internal static class Logging
6{
7    public static class ConsoleLogger
8    {
9        public static void Write(string message) => Console.WriteLine(message);
10    }
11}
12
13internal class Calculator
14{
15    [Log]
16    public int Add(int a, int b)
17    {
18        Logging.ConsoleLogger.Write("Executing Calculator.Add(int, int).");
19        return a + b;
20    }
21}
22

See also