System.Reflection.AmbiguousMatchException : Why extending Silverlight through sub-classing might result in this error.

Earlier this week we spotted we had a problem with a Silverlight application that has been live for a while.  We were only able to reproduce it with the Silverlight 4 runtime installed and not the Silverlight 3 runtime.  The reason is actually quite interesting from an academic point of view, but also raises some factors that developers need to take into account when designing their applications.

Because of the way that the Silverlight runtime is deployed it is very possible that an application that you write is compiled against one runtime but is executing against another.  In our case we have a Silverlight 3 compiled application running against the Silverlight 4 runtime.  Now the product group do an awful lot to ensure backwards compatibility, so much so that SL4 includes a ‘Quirks Mode’ so that the where bug fixes introduce breaking changes existing applications will not be affected.

The particular case we discovered doesn’t seem to be included in this though.  The exception we saw was

System.Reflection.AmbiguousMatchException: Ambiguous match found.

   at System.RuntimeType.GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)

   at System.Type.GetProperty(String name, BindingFlags bindingAttr)

   at MS.Internal.FrameworkCallbacks.SetNonAttachedProperty(Object target, String propertyName, Object propertyValue, Int32 typeIndex)

   at MS.Internal.FrameworkCallbacks.SetValueToProperty(Object target, String propertyName, Object propertyValue, Int32 typeIndex, String attachedDPOwnerNamespace, String attachedDPOwnerAssembly)

   at MS.Internal.FrameworkCallbacks.SetPropertyAttribute(IntPtr nativeTarget, String attrName, String attrValue, String attachedDPOwnerNamespace, String attachedDPOwnerAssembly) [Line: 0 Position: 0]

A particularly descriptive exception you’ll admit?

Basically this comes down to us having sub-classed the TextBox control in order to make a WatermarkedTextBox by adding a dependency property called Watermark.  This is an issue because the Silverlight 4 Textbox class now has it’s own Watermark property.  This would obviously result in a compile time error when building against the SL4 toolkit, but because we are running SL3 compiled code against the SL4 runtime, when the XAML parse happens for this control it throws an exception!

The quickest and easiest solution is to rename the offending property, possibly adding a custom descriptor to the beginning like ‘contosoWatermark’, although this isn’t ideal.  Another alternative is to encapsulate rather than subclass by creating a new class which inherits from control, an example of which is given in my post on creating a localizable TextBlock.  Unfortunately both of these solutions require code changes and a redeployment.

Thinking about the general case of a 3rd party having extended a base class to add a new property and then that same property being added to the base class in a newer version of Silverlight.  If Quirks Mode or some other backwards compatibility mechanism doesn’t handle this, then there are design repercussions when extending a Silverlight base class.

Food for thought.

Written by Simon Middlemiss

Comments (1)

  1. laOrient says:

    Another torture, as I found out, is the Watermark property in SL4 TextBox is Not Implemented! I chose to just rename it to WatermarkText so it can work.