Create Method - Ambiguous match found Exception

Topics: Policy Injection Application Block
Dec 13, 2007 at 2:46 PM
I have a Class A with no explicit constructor, that inherits from Class B which has an explicit empty constructor defined.
Class B inherits Class C with no explicit constructor, and Class C inherits Class D which has another explicit empty constructor defined.
When I call PolicyInjection.Create(Of Class A)(), this throws the "Ambiguous match found" exception.
Could this be related with the fact of having multiple constructors with the same signature in different
points of the inheritance hierachy ? And if this is the case, how can I solve it ?
Thanks in advance.
Javier.
Dec 14, 2007 at 11:22 AM
Javier,

Can you post the stack trace? Constructors are not inherited, so this cannot be the cause of your problem.

Fernando
Dec 17, 2007 at 7:53 PM
You were right Fernando, the problem was not caused by the constructors. Here I post the stack trace:

Stack Trace :

at System.RuntimeType.GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
at System.Type.GetProperty(String name)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Utilities.ReflectionHelper.GetPropertyFromMethod(MethodBase method)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Utilities.ReflectionHelper.GetAllAttributesTAttribute(MemberInfo member, Boolean inherits)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.AttributeDrivenPolicy.DoesMatch(MethodBase member)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.AttributeDrivenPolicy.<DoesApplyTo>b__8(MethodInfo method)
at System.Array.FindIndexT(T[] array, Int32 startIndex, Int32 count, Predicate`1 match)
at System.Array.FindIndexT(T[] array, Predicate`1 match)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.AttributeDrivenPolicy.DoesApplyTo(Type t)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicySet.CalculatePoliciesForType(Type t)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicySet.GetPoliciesFor(Type t)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.CreateTObject(Object[] args)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.CreateTObject(Object[] args)

Thanks again
Dec 17, 2007 at 8:33 PM
Hi Javier,

Are there any duplicate properties, maybe defined with the new modifier in your hierarchy? It looks like the property lookup in ReflectionHelper.GetPropertyFromMethod() should use the BindingFlags.DeclaredOnly option to avoid this problem. I think I saw a similar thread before, but I'm logging it as a bug anyway.

Can you please verify whether the property you are using is redefined elsewhere? If that's the case, is it possible for you to change your code to work around this issue?

Fernando
Dec 17, 2007 at 8:34 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Dec 18, 2007 at 12:20 PM
Hi Fernando,

After eliminating the constructors, the problem persists, In response to your question, first of all I have to tell you I´m working with VB.Net, and I think new modifier is not available. Anyway, I checked the properties in each class and found one duplicate property.
Remember I have a Class A that inherits from Class B, Class B inherits Class C and Class C inherits Class D.
In Class C I have a public, readonly MustOverride property which is overridden and implemented in Class A:

In Class C:
Public MustOverride ReadOnly Property Prop1() As T1

In Class A:
Public Overrides ReadOnly Prop1 As T1

I hope this helps. If you need something else please let me know.
Thanks, Javier.
Dec 18, 2007 at 1:03 PM
A little more information about the definition of the property overriden:

In Class C:
Public MustOverride ReadOnly Property Prop1() As T1(Of TipoBase)

In Class A:
Public Overrides ReadOnly Prop1 As T1(Of TipoHeredado)

Where TipoHeredado inherits TipoBase and T1 is a Generic Type.

Thanks again.
Dec 18, 2007 at 1:32 PM
Hi,

This shouldn't cause the problem. Can you send isolated repro code that shows the issue?

I tried this based on your description and didn't get the error (C#, but shouldn't make a difference).

namespace PiabMatchRepro
{
class Program
{
static void Main(string[] args)
{
A instance = PolicyInjection.Create<A>();
}
}

public abstract class D : MarshalByRefObject { }

public abstract class C : D
{
public abstract int MyProperty { get; }
}

public abstract class B : C { }

public class A : B
{
ValidationCallHandler
public override int MyProperty
{
get { return 0; }
}
}
}
Dec 18, 2007 at 1:49 PM
Is it possible you have mixed static and non-static properties with the same name in the hierarchy?

Fernando
Dec 18, 2007 at 4:52 PM
I checked what you said about static and non-static properties but it's not happenning. Besides I tried this. I comment the call to the PolicyInjection.Create(Of Class A)() Method.
And added, just to test, a call to the System.Type.GetProperty(String Name) Method, passing to this, the name of the property overriden (Prop1). I did this because I saw, in the stack trace, that this method was called after the GetPropertyFromMethod(MethodBase method).
And I got the same error, so I think the problem is on that Property definition. Anyway I'll try to isolate the code that shows the issue and send it to you.

Thanks again, Javier.
Dec 18, 2007 at 7:38 PM
I think I found the problem. I changed Prop1 from Public to Protected and the error dissapeared. Despite
of this, I ´m finishing the example that I´m going to send you..
Thanks a lot.
Dec 19, 2007 at 12:05 PM
Hi,

That of course will only be a solution if you can make that property protected (ie no other class uses it), and it works because by making it protected it's no longer considered by the current property lookup code.

Looking forward for your repro code.

Bye,
Fernando
Dec 19, 2007 at 3:17 PM
Hi Fernando,

I attached the repro code at the issue tracker (I post this just in the case you haven´t been notified).
I hope it could help.

Bye, Javier.
Dec 19, 2007 at 4:30 PM
Hi Javier,

I missed the post with the extra information about the generic nature of the properties involved; the post just happened while I was working on my repro. This is causing the ambiguous match, and it does get fixed with a query for declared only properties in the implementation for ReflectionHelper as originally suggested.

As a workaround, you could try having two properties in your generic base class: a generic, abstract and protected "MyPropertyInternal" property, and a generic, non abstract public property "MyProperty" that just returns the value for MyPropertyInternal. The derived class would only provide an implementation for the protected property.

Hope this helps,
Fernando