| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot bind field "<Field>" to event "<Event>": the event type is incompatible with the field type. |
Cause
An aspect imports an event of its target class with a field of type Event<TDelegate> annotated with ImportMemberAttribute. PostSharp finds the event by its name, then compares its delegate type with the type argument of the field. The two types must be the same: a delegate type with the same signature, such as EventHandler<PropertyChangedEventArgs> for a PropertyChangedEventHandler event, is not accepted.
When they differ, PostSharp reports LA0083 on the target type, not on the field of the aspect. The severity depends on the IsRequired property: an error when it is true, a warning when it is false, which is the default. After the warning, PostSharp still binds the field to the event.
In the following example, the [TraceChanges] aspect imports the PropertyChanged event of Customer, whose type is PropertyChangedEventHandler, into a field of type Event<EventHandler>.
using System;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0083_Error;
[PSerializable]
public class TraceChangesAttribute : InstanceLevelAspect
{
// The PropertyChanged event of Customer is a PropertyChangedEventHandler, not an EventHandler.
[ImportMember( "PropertyChanged", IsRequired = true )]
public Event<EventHandler>? PropertyChanged;
public override void RuntimeInitializeInstance()
{
this.PropertyChanged!.Add( ( sender, args ) => Console.WriteLine( "A property changed." ) );
}
}
[TraceChanges]
public class Customer
{
private string name = "Alice";
public event PropertyChangedEventHandler? PropertyChanged;
public string Name
{
get => this.name;
set
{
this.name = value;
this.PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof(this.Name) ) );
}
}
}
public static class Program
{
public static void Main()
{
new Customer().Name = "Bob";
}
}
error LA0083: LA0083_Error.cs(23,14): Cannot bind field "Errors.LA0083_Error.TraceChangesAttribute.PropertyChanged" to event "Errors.LA0083_Error.Customer.PropertyChanged": the event type is incompatible with the field type.
Resolution
Give the field the type Event<TDelegate> with the delegate type of the event as the type argument, and adapt the handlers that the aspect adds through Add to this delegate type. Treat the warning of an optional import like the error: the field does not match the event.
In the following example, the field has the type Event<PropertyChangedEventHandler>, and the handler reads the name of the changed property.
using System;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0083_Fixed;
[PSerializable]
public class TraceChangesAttribute : InstanceLevelAspect
{
// The type argument of Event<T> is the delegate type of the PropertyChanged event.
[ImportMember( "PropertyChanged", IsRequired = true )]
public Event<PropertyChangedEventHandler>? PropertyChanged;
public override void RuntimeInitializeInstance()
{
this.PropertyChanged!.Add( ( sender, args ) => Console.WriteLine( $"The property {args.PropertyName} changed." ) );
}
}
[TraceChanges]
public class Customer
{
private string name = "Alice";
public event PropertyChangedEventHandler? PropertyChanged;
public string Name
{
get => this.name;
set
{
this.name = value;
this.PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof(this.Name) ) );
}
}
}
public static class Program
{
public static void Main()
{
new Customer().Name = "Bob";
}
}
The property Name changed.
See Also
Reference
ImportMemberAttribute
Event<TDelegate>
Other Resources