| Severity | Error |
| Reported by | PostSharp |
| Message | The type '<MemberType>' of member '<Element>.<Member>' cannot be set in an XML configuration file. Use a field or property of an intrinsic type, an enumeration, System.Type, or an array of these types. |
Cause
The Multicast element of a postsharp.config file adds aspects or other multicast attributes to the project without changing its source code, as Adding Aspects Using XML describes. Each XML attribute of a child element sets the public field or property of the same name of the attribute class.
PostSharp can convert the text of an XML attribute only into the following types: the intrinsic types (bool, char, the integer and floating-point types, and string), enumerations, Type, and arrays of these types. PostSharp reports PS0168 when the XML attribute sets a field or property of another type, for example TimeSpan, DateTime, Guid, decimal or object. <Element> is the local name of the XML element, and <Member> is the name of the XML attribute. The location of the message is the XML attribute in the postsharp.config file.
In the following example, postsharp.config sets the Threshold property of the [WarnIfSlow] aspect, which is a TimeSpan.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
<Multicast xmlns:my="clr-namespace:Errors.PS0168_Error;assembly:PS0168_Error">
<!-- The Threshold property is a TimeSpan. -->
<my:WarnIfSlowAttribute AttributeTargetTypes="Errors.PS0168_Error.OrderService" AttributeTargetMembers="PlaceOrder" Threshold="00:00:00.500" />
</Multicast>
</Project>
using System;
using System.Diagnostics;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.PS0168_Error;
// postsharp.config applies this aspect to OrderService.PlaceOrder and sets its Threshold property.
[PSerializable]
public class WarnIfSlowAttribute : OnMethodBoundaryAspect
{
// A TimeSpan property cannot be set in postsharp.config.
public TimeSpan Threshold { get; set; } = TimeSpan.FromSeconds( 1 );
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Timing {args.Method.Name} against a threshold of {this.Threshold.TotalMilliseconds} ms." );
args.MethodExecutionTag = Stopwatch.StartNew();
}
public override void OnExit( MethodExecutionArgs args )
{
Stopwatch stopwatch = (Stopwatch) args.MethodExecutionTag;
if ( stopwatch.Elapsed > this.Threshold )
{
Console.WriteLine( $"Warning: {args.Method.Name} took {stopwatch.ElapsedMilliseconds} ms." );
}
}
}
public class OrderService
{
public void PlaceOrder( string product )
{
Console.WriteLine( $"Order placed for {product}." );
}
}
public static class Program
{
public static void Main()
{
new OrderService().PlaceOrder( "Coffee" );
}
}
error PS0168: postsharp.config(5,121): The type 'System.TimeSpan' of member 'WarnIfSlowAttribute.Threshold' cannot be set in an XML configuration file. Use a field or property of an intrinsic type, an enumeration, System.Type, or an array of these types.
Resolution
- Replace the member by one of a supported type, and convert its value in the aspect: for example, an
intnumber of milliseconds instead of a TimeSpan, or astringthat the aspect parses. - Set the member in code instead, where the attribute is applied with C#, or initialize it in the aspect.
The formats of the supported types are described in Including CLR Objects in Configuration.
In the following example, the aspect has a ThresholdMilliseconds property of type int, which postsharp.config sets.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
<Multicast xmlns:my="clr-namespace:Errors.PS0168_Fixed;assembly:PS0168_Fixed">
<!-- The ThresholdMilliseconds property is an int. -->
<my:WarnIfSlowAttribute AttributeTargetTypes="Errors.PS0168_Fixed.OrderService" AttributeTargetMembers="PlaceOrder" ThresholdMilliseconds="500" />
</Multicast>
</Project>
using System;
using System.Diagnostics;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.PS0168_Fixed;
// postsharp.config applies this aspect to OrderService.PlaceOrder and sets its ThresholdMilliseconds property.
[PSerializable]
public class WarnIfSlowAttribute : OnMethodBoundaryAspect
{
// An int property can be set in postsharp.config.
public int ThresholdMilliseconds { get; set; } = 1000;
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Timing {args.Method.Name} against a threshold of {this.ThresholdMilliseconds} ms." );
args.MethodExecutionTag = Stopwatch.StartNew();
}
public override void OnExit( MethodExecutionArgs args )
{
Stopwatch stopwatch = (Stopwatch) args.MethodExecutionTag;
if ( stopwatch.ElapsedMilliseconds > this.ThresholdMilliseconds )
{
Console.WriteLine( $"Warning: {args.Method.Name} took {stopwatch.ElapsedMilliseconds} ms." );
}
}
}
public class OrderService
{
public void PlaceOrder( string product )
{
Console.WriteLine( $"Order placed for {product}." );
}
}
public static class Program
{
public static void Main()
{
new OrderService().PlaceOrder( "Coffee" );
}
}
Timing PlaceOrder against a threshold of 500 ms.
Order placed for Coffee.
See Also
Other Resources
Adding Aspects Using XML
Including CLR Objects in Configuration
Configuring Projects Using postsharp.config