Open sandboxFocusImprove this doc

PS0264: Assembly, Type or Member Cannot Be Loaded

Severity Error
Reported by PostSharp
Message <Reason> <LogReference> When the error is about loading an assembly, also check that this project does not reference a project with a different processor architecture (x86/x64/arm64).

Cause

At build time, PostSharp loads the assemblies of the project and of its references, executes the build-time code of the aspects, and binds the types and members that this code returns to the declarations of the assemblies. PostSharp reports PS0264, without a source location, when one of these operations fails:

  • An assembly cannot be loaded: it cannot be found, a different version is found, or it cannot be loaded into the process of PostSharp, for example because it targets another processor architecture.
  • A type cannot be loaded or bound.
  • A member that the build-time code returns, for example from a method pointcut, matches several declarations of the assembly.

<Reason> is the message of the failure. <LogReference> refers to the PS0265 message that follows the error, which gives the assembly loading log. PostSharp reports this log once per assembly: the next errors about the same assembly refer to the PS0265 message of the first one.

In the following example, the Trace aspect selects the methods of NativeCallbackService with MethodPointcut. One Invoke method takes a function pointer and the other takes an IntPtr. PostSharp cannot match the MethodInfo of Invoke that the pointcut returns with a single declaration, because the two overloads look the same to reflection.

// @SkipILVerify
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.PS0264_Error;

[PSerializable]
public class TraceAttribute : TypeLevelAspect
{
    // Methods that take a function pointer cannot be advised, so the advice skips them.
    [OnMethodEntryAdvice( UnsupportedTargetAction = UnsupportedTargetAction.Ignore )]
    [MethodPointcut( nameof(SelectMethods) )]
    public void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}." );
    }

    private IEnumerable<MethodInfo> SelectMethods( Type type )
    {
        return type.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly );
    }
}

[Trace]
public unsafe class NativeCallbackService
{
    public int Invoke( delegate*<int> callback ) => callback();

    // Reflection cannot tell this overload from the one that takes a function pointer.
    public int Invoke( IntPtr callback ) => ((delegate*<int>) callback)();
}

public static unsafe class Program
{
    private static int GetAnswer() => 42;

    public static void Main()
    {
        Console.WriteLine( new NativeCallbackService().Invoke( &GetAnswer ) );
    }
}
error PS0264: Ambiguous match for method Invoke in type Errors.PS0264_Error.NativeCallbackService. See the PS0265 message that follows for the assembly loading log. When the error is about loading an assembly, also check that this project does not reference a project with a different processor architecture (x86/x64/arm64).

Resolution

Read <Reason> and the PS0265 message that follows the error. Then, depending on the cause:

  • When an assembly cannot be found, check that the project references it, directly or through a package, and that the build copies it next to the other references.
  • When a different version of an assembly is found, align the versions of the packages that the projects of the solution reference. See Resolution of Assembly Binding Redirections for how PostSharp resolves the versions of the assemblies.
  • When the assembly targets another processor architecture, check that the project does not reference a project or an assembly built for another platform, such as x86 when the project targets x64.
  • When a member matches several declarations, give the overloads distinct names, or change the build-time code so that it does not return the ambiguous members.

To see where PostSharp searches for the assemblies, capture the AssemblyBinder trace category with the PostSharpTrace MSBuild property, as Well-Known MSBuild Properties describes.

In the following example, the overload that takes an address is renamed InvokeAddress. The aspect skips the method that takes a function pointer, because the UnsupportedTargetAction property of its advice is Ignore, and traces InvokeAddress.

// @SkipILVerify
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.PS0264_Fixed;

[PSerializable]
public class TraceAttribute : TypeLevelAspect
{
    // Methods that take a function pointer cannot be advised, so the advice skips them.
    [OnMethodEntryAdvice( UnsupportedTargetAction = UnsupportedTargetAction.Ignore )]
    [MethodPointcut( nameof(SelectMethods) )]
    public void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.Name}." );
    }

    private IEnumerable<MethodInfo> SelectMethods( Type type )
    {
        return type.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly );
    }
}

[Trace]
public unsafe class NativeCallbackService
{
    public int Invoke( delegate*<int> callback ) => callback();

    // The overload that takes an address has a name of its own.
    public int InvokeAddress( IntPtr callback ) => ((delegate*<int>) callback)();
}

public static unsafe class Program
{
    private static int GetAnswer() => 42;

    public static void Main()
    {
        Console.WriteLine( new NativeCallbackService().Invoke( &GetAnswer ) );
        Console.WriteLine( new NativeCallbackService().InvokeAddress( (IntPtr) (delegate*<int>) &GetAnswer ) );
    }
}
42
Entering InvokeAddress.
42

See Also

Reference

MethodPointcut
UnsupportedTargetAction

Other Resources

Resolution of Assembly Binding Redirections
Well-Known MSBuild Properties