| Severity | Error |
| Reported by | PostSharp |
| Message | Type of field "<Field>" is invalid. Valid types for fields bound to an ImportLocationAdviceInstance or an ImportMethodAdviceInstance are: Delegate, Event<T>, Property<TValue>, Property<TValue,TIndex>, ILocationBinding, or a class that implements ICollection<ILocationBinding> and has a public default constructor. |
Cause
An aspect that implements IAdviceProvider imports members of its target class into its own fields with an ImportLocationAdviceInstance or an ImportMethodAdviceInstance. The type of the aspect field, <Field>, tells PostSharp what to assign at run time: a delegate for a method, Event<TDelegate> for an event, Property<TValue> or Property<TValue, TIndex> for a property, ILocationBinding for a field or a property, or a collection that receives one ILocationBinding per advice. PostSharp reports LA0140 in two cases:
- The field has another type. PostSharp then reports the message on the aspect class.
- The field is a collection of ILocationBinding, but its type has no public default constructor, for example the interface
IList<ILocationBinding>. PostSharp creates the collection with this constructor before it adds the bindings. It then reports the message on the aspect field.
With ImportMemberAttribute, the same mistake causes LA0074.
In the following example, the [Describe] aspect imports the fields of Customer into a field of type IList<ILocationBinding>.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0140_Error;
[PSerializable]
public class DescribeAttribute : InstanceLevelAspect, IAdviceProvider
{
// PostSharp cannot create an instance of an interface to hold the bindings.
[PNonSerialized]
public IList<ILocationBinding>? Fields;
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
Type targetType = (Type) targetElement;
FieldInfo aspectField = typeof(DescribeAttribute).GetField( nameof(this.Fields) )!;
foreach ( FieldInfo field in targetType.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly ) )
{
yield return new ImportLocationAdviceInstance( aspectField, new LocationInfo( field ) );
}
}
public override void RuntimeInitializeInstance()
{
foreach ( ILocationBinding binding in this.Fields! )
{
Console.WriteLine( $"{binding.LocationInfo.Name} = {binding.GetValue( this.Instance! )}" );
}
}
}
[Describe]
public class Customer
{
private string name = "Alice";
private int orderCount = 3;
public override string ToString() => $"{this.name}, {this.orderCount} orders";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new Customer() );
}
}
error LA0140: LA0140_Error.cs(16,37): Type of field "Errors.LA0140_Error.DescribeAttribute.Fields" is invalid. Valid types for fields bound to an ImportLocationAdviceInstance or an ImportMethodAdviceInstance are: Delegate, Event<T>, Property<TValue>, Property<TValue,TIndex>, ILocationBinding, or a class that implements ICollection<ILocationBinding> and has a public default constructor.
Resolution
Give the aspect field a supported type: ILocationBinding to import one field or property, a class such as List<ILocationBinding> to import several of them with one advice each, or a delegate, Event<TDelegate> or Property<TValue> for the other kinds of members.
In the following example, the aspect field is a List<ILocationBinding>, and the aspect receives the two fields of Customer.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0140_Fixed;
[PSerializable]
public class DescribeAttribute : InstanceLevelAspect, IAdviceProvider
{
// PostSharp creates the list with its public default constructor and adds one binding per advice.
[PNonSerialized]
public List<ILocationBinding>? Fields;
public IEnumerable<AdviceInstance> ProvideAdvices( object targetElement )
{
Type targetType = (Type) targetElement;
FieldInfo aspectField = typeof(DescribeAttribute).GetField( nameof(this.Fields) )!;
foreach ( FieldInfo field in targetType.GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly ) )
{
yield return new ImportLocationAdviceInstance( aspectField, new LocationInfo( field ) );
}
}
public override void RuntimeInitializeInstance()
{
foreach ( ILocationBinding binding in this.Fields! )
{
Console.WriteLine( $"{binding.LocationInfo.Name} = {binding.GetValue( this.Instance! )}" );
}
}
}
[Describe]
public class Customer
{
private string name = "Alice";
private int orderCount = 3;
public override string ToString() => $"{this.name}, {this.orderCount} orders";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new Customer() );
}
}
name = Alice
orderCount = 3
Alice, 3 orders
See Also
Reference
IAdviceProvider
ImportLocationAdviceInstance
ImportMethodAdviceInstance
ILocationBinding
Other Resources
Providing Advices Dynamically
Accessing Members of the Target Class