vendredi 23 décembre 2022

CreateDelegate: "ArgumentException: Cannot bind to the target method because its signature is not compatible with that of the delegate type."

I am writing a GUI program using AvaloniaUI. The part I'm stuck on right now is that I'm trying to add some code to the ViewModel's constructor that binds some methods to events defined in the VM using Reflection. This is what I have right now:

namespace Program
{
    [AttributeUsage(AttributeTargets.Method)]
    [MeansImplicitUse]
    internal sealed class AttachToEventInViewModelAttribute : Attribute
    {
        internal string EventName;

        public AttachToEventInViewModelAttribute(string EventName) =>
            this.EventName = EventName;
    }
}

namespace Program.Models
{
    public static class ExtractFiles
    {
        [AttachToEventInViewModel("onStartExtraction")]
        internal static void Extract()
        {
        }
    }
}

namespace Program.Views
{
    public partial class MainWindow : Window
    {
        private readonly Window instance;

        public MainWindow()
        {
            instance = this;
            InitializeComponent();
        }

        [AttachToEventInViewModel("onGetWindow")]
        public Window GetInstance() =>
            instance;
    }
}

namespace Program.ViewModels
{
    public sealed class MainWindowViewModel : ViewModelBase
    {
        // ==== Constructor ====
        public MainWindowViewModel()
        {
            <snip code for finding the GetInstance() and Extract() methods, which is working>
            
            MethodInfo method = allMethodsInType[j];
            object[] allAttributesOnMethod = method.GetCustomAttributes(typeof(AttachToEventInViewModelAttribute), false);

            AttachToEventInViewModelAttribute methodAttribute = (AttachToEventInViewModelAttribute) allAttributesOnMethod[0];
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic;

            EventInfo? methodEventInfo = this.GetType().GetEvent(methodAttribute.EventName, bindingFlags);
            if (methodEventInfo == null)
                continue;

            Type? methodEventType = methodEventInfo.EventHandlerType;
            if (methodEventType == null)
                continue;

            Delegate methodEventHandler = Delegate.CreateDelegate(methodEventType, this, method);
            methodEventInfo.AddEventHandler(this, methodEventHandler);
        }


        // ==== Events ====
        private event Action onStartExtraction;

        private event Func<Window> onGetWindow;
    }
}

However, when I try run this code, the CreateDelegate method triggers the Exception in the title. The strange part is that if I add the following lines to the MainWindowViewModel constructor, the compiler has no problem with them, implying that the signatures are actually compatible:

            onGetWindow += new MainWindow().GetInstance;
            onStartExtraction += ExtractFilesFromBsaRecords.Extract;

I searched the site and found other questions with this problem, but none of them helped. For the most part, the problem in those was that the asker used the CreateDelegate overload for static events.





Aucun commentaire:

Enregistrer un commentaire