Skip to content

Duplicate Event Handlers

Jonathan Pobst edited this page Apr 7, 2021 · 4 revisions

When the bindings process sees something in the Java API that looks like an "event", it creates a C# event so that it feels more familiar for .NET users. It also needs to create an internal "Implementor" class to bridge the Java "Listener" class to the C# event.

For example:

public interface PropertyChangeListener
{
    void onPropertyChange (string property);
}

Generates:

public partial interface IPropertyChangeListener
{
    void OnPropertyChange (string property);
}

internal sealed partial class IPropertyChangeListenerImplementor : Java.Lang.Object
{
    public EventHandler<OnPropertyChangeEventArgs> OnPropertyChangeHandler;

    public void OnPropertyChange (string property) { ... }
}

The names of these various internal implementation bits are derived from the original method name OnPropertyChange:

  • OnPropertyChangeHandler
  • OnPropertyChangeEventArgs

However, if there are two methods with the same name, the bindings process does not know to give them distinct names, and thus creates duplicate Handlers:

public interface PropertyChangeListener
{
    void onPropertyChange (string property);
    void onPropertyChange (string property, object value);
}

Generates:

public partial interface IPropertyChangeListener
{
    void OnPropertyChange (string property);
    void OnPropertyChange (string property, Java.Lang.Object value);
}

internal sealed partial class IPropertyChangeListenerImplementor : Java.Lang.Object
{
    public EventHandler<OnPropertyChangeEventArgs> OnPropertyChangeHandler;
    public EventHandler<OnPropertyChangeEventArgs> OnPropertyChangeHandler;

    public void OnPropertyChange (string property) { ... }
    public void OnPropertyChange (string property, Java.Lang.Object value) { ... }
}

This results in compilation errors like:

Error CS0102: The type 'MyClass.IPropertyChangeListenerImplementor' already contains a definition for 'OnPropertyChangeHandler'

In order to fix this, we can use metadata to rename either of the duplicate method names using managedName. Because the Handler name is derived from the method name, this will rename the duplicate Handler name as well:

<attr path="/api/package[@name='com.example']/interface[@name='PropertyChangeListener']/method[@name='onPropertyChange' and count(parameter)=2]" name="managedName">OnPropertyChange2</attr>

Note your XPath path will need to be more specific than just the method name, or else you will rename both of the methods, which will not fix the issue.

Now the methods will be generated as OnPropertyChange and OnPropertyChange2, which fixes the duplication:

public partial interface IPropertyChangeListener
{
    void OnPropertyChange (string property);
    void OnPropertyChange2 (string property, Java.Lang.Object value);
}

internal sealed partial class IPropertyChangeListenerImplementor : Java.Lang.Object
{
    public EventHandler<OnPropertyChangeEventArgs> OnPropertyChangeHandler;
    public EventHandler<OnPropertyChange2EventArgs> OnPropertyChange2Handler;

    public void OnPropertyChange (string property) { ... }
    public void OnPropertyChange2 (string property, Java.Lang.Object value) { ... }
}