What causes an AmbiguousMatchException

What causes an AmbiguousMatchException

Old forum URL: forums.lhotka.net/forums/t/5788.aspx


AKaplan posted on Tuesday, November 11, 2008

Some of my BO's work without a problem and some don't. I'm not seeing a difference between the BO's, but i might need another pair of eyes. On this one simple BO i continuously am getting a ambiguous match exception. I don't know what causes it. Can anyone tell me, so i know what to look for in the debugging process.

vdhant replied on Tuesday, November 11, 2008

I would guess that it would be generated by MethodCaller. This is in the Csla.Reflection namespace. There is a fair amount of logic that goes on in hear to dynamically execute methods and more importantly what version of the method to execute.

It is mainly used by the Data Portal and the Data Mapper (and a little by some Wpf stuff). If your getting this error it probably means is that you have a case where it can't decide which overload to use in the inheritance chain. Meaning you probably have a command object that is being passed into a DataPortal_xyz and you have two versions of DataPortal_xyz and it can't pick between the 2.

Hope that helps
Anthony

vdhant replied on Tuesday, November 11, 2008

Note if it is the MethodCalled, the exception is most likely being generated in one of two places;

    public static MethodInfo FindMethod(Type objectType, string method, Type[] types)
    {
      MethodInfo info = null;
      do
      {
        // find for a strongly typed match
        info = objectType.GetMethod(method, oneLevelFlags, null, types, null);
        if (info != null)
        {
          break; // match found
        }

        objectType = objectType.BaseType;
      } while (objectType != null);

      return info;
    }

or

    public static MethodInfo GetMethod(Type objectType, string method, params object[] parameters)
    {

      MethodInfo result = null;

      object[] inParams = null;
      if (parameters == null)
        inParams = new object[] { null };
      else
        inParams = parameters;

      // try to find a strongly typed match

      // first see if there's a matching method
      // where all params match types
      result = FindMethod(objectType, method, GetParameterTypes(inParams));

      if (result == null)
      {
        // no match found - so look for any method
        // with the right number of parameters
        try
        {
          result = FindMethod(objectType, method, inParams.Length);
        }
        catch (AmbiguousMatchException)
        {
          // we have multiple methods matching by name and parameter count
          result = FindMethodUsingFuzzyMatching(objectType, method, inParams);
        }
      }

      // no strongly typed match found, get default based on name only
      if (result == null)
      {
        result = objectType.GetMethod(method, allLevelFlags);
      }
      return result;
    }

In both cases the GetMethod is not in a try catch block.

AKaplan replied on Tuesday, November 11, 2008

Well you are right about that... I do have a few different DataPortal_Fetch statements which have different parameters. Also why can't I have multiple DataPortal_Fetch statements with different parameters? Ok that statement is within a try catch statement. i just checked. I'm using csla 3.5. This is where I am erroring out in the second FindMethod

Exception Details: System.Reflection.AmbiguousMatchException: Ambiguous match found.

Source Error:


Line 322: Dim currentType As Type = objectType
Line 323: Do
Line 324: Dim info As MethodInfo = currentType.GetMethod(method, oneLevelFlags)
Line 325: If info IsNot Nothing Then
Line 326: Dim infoParams = info.GetParameters()

Source File: D:\cslavb-3.5.0-080330\cslavb\Csla\Reflection\MethodCaller.vb Line: 324

vdhant replied on Tuesday, November 11, 2008

"Also why can't I have multiple DataPortal_Fetch statements with different parameters?" You should be able to. There must be an edge case that isn't being dealt with.

What I would recommend is that you give us a copy of the signatures of the DataPortal_Fetch methods along with the inheritance structure for any classes that are being passed into the DataPortal_Fetch.

In addition this is a post that I raised previously about this very issue:
http://forums.lhotka.net/forums/thread/20080.aspx

Here is what I said:
"Hi Rocky,
That was me who said that i think i have found a potential bug.

In the public static MethodInfo FindMethod(Type objType, string method, int parameterCount) method, it does a loop looking for methods that have a set number of paramerters. Within the loop it uses this MethodInfo info = currentType.GetMethod(method, oneLevelFlags); line which calls the GetMethod method. As far as i can see anywhere the GetMethod is used it has the ability to throw an AmbiguousMatchException exectipion. Now when you are doing calling this public static MethodInfo FindMethod(Type objType, string method, Type[] types) method, you should never get this because you can't compile with two methods of the same signature, but with the count version ther e is the possibility that it could. Hence why i thought that this is a bug and should have a try catch around it. You will see in code that i provided that it checks for this case and it the exception occurs runs the pretty much the same code that you have in the only AmbiguousMatchException expectation check at the moment. It probably has not arisen as a bug in many cases thus far because i imagine that the first findmethod would pick up most cases.

As far as a performance testing goes, I don't really have the setup to be able to give you figures on that one, but what i do know is that there is a lot of looping that occurs to find the correct method and this looping logic, given a type, method name and a set of params is always going to produce the same result. Hence is there need to conduct that looping and reflection every time. Hence why i was trying to cache the results. I guess you now have a dictionary lookup and a lock to deal with if the method isn't found in that type but for the vast majority of cases i would imagine that there would have to be some tangible performance improvement.

Anthony"

This is what Rocky said in reply:
"I'd like to see a test case that causes failure before solving a theoretical problem.

In other words, if there’s some combination of declared methods that can make the failure occur I’ll put it into my MethodCallerTest app as a test and that way we can establish that the solution directly solves the issue.

Rocky"

Looks like we might have found the edge case I was talking about.
Cheers
Anthony

AKaplan replied on Tuesday, November 11, 2008

ah man i'm a big dumbass i know what is causing the problem... it was just a small oversight. apparently i didnt have the right dataportal parameters method in place.

Copyright (c) Marimer LLC