views:

268

answers:

2

I'm calling some VB.NET code in one assembly from C# code in another assembly. The code builds fine, but I'm getting MissingMethodException when I make the call.

Usually, according to the Stack Overflow and Google search results for MethodMissingException I've read, it's due to a mismatch between the DLLs you're building against and the DLLs you're running against. None of the results mention a third DLL. More on that below.

I've confirmed that:

  • The target DLL's path matches the reference's path, according to the VS2008 Output window while debugging
  • That's the only version of the target DLL loaded on the system, according to ProcExp
  • The “missing” method is present according to the code
  • The “missing” method is present according to the generated XML documentation
  • The “missing” method is present according to Reflector

The strongest lead is the duplicate loading of an assembly containing a type used in the signature of the “missing” method. It's coming from both SecondParty (which I reference) and FirstParty (which has copy local set off).

Manually copying everything to a new directory fixes the problem. That makes debugging tricky, though: I like just hitting the green triangle.

Detail:

I have a third assembly with a strongly typed ADO.NET DataSet. Let's call the type ThirdParty.PortableData. My FirstParty is filling it with data and passing it to SecondParty.

The calling code in FirstParty that's failing looks something like this:

ThirdParty.PortableData data = GetPortableData()
SecondParty instance = new SecondParty()
instance.Data = data

(The MissingMethodException is thrown from the line that calls the method with this code in it.)

The target code in SecondParty that FirstParty can't seem to find at runtime looks like this:

Public Property Data() As ThirdParty.PortableData
    Get
        ' ...
    End Get

    Set(ByVal value As ThirdParty.PortableData)
        ' ...
    End Set
End Property

I've also tried, with slightly different calling code:

Public Sub SetData(ByVal value as ThirdParty.PortableData) 
    ' ...
End Sub

The ThirdParty DLL is being loaded from more than one place, according to VS2008 and ProcExp — once from the reference path, and once from a build directory. The MD5 digests of the DLLs match.

If I copy everything into a new directory, ensuring there's only one copy of the ThirdParty DLL, the program works fine.

All references to ThirdParty have “Copy Local” turned off. Yet, a copy is sitting in FirstParty\bin\Debug.

What else should I check? How can I prevent MissingMethodException during debug, apart from post-build scripts that copy the build products around?

A: 

Copy all of the files off to a new, clean machine. Hash all of those files to make sure you have a unique value for each dll, don't trust version numbers. See if the problem exists. My guess is that your issue would be fixed on the clean machine.

If it works, then go back to your machine and do a global search for each DLL and run the hash on it and make sure it is the same EXACT file you are expecting.

I have this happen alot where people hardcode their version numbers (1.0.0.0) and then have 5 different copy of DLLs on their machine (local directory, shared folders, GAC, etc.)

JasonRShaver
Jason, all the DLLs match. Yet, one DLL is being loaded twice — and that's causing MethodMissingException. Would strong names help?
Garth T Kidd
strong naming will fix the issue and is always a good idea. It is a requirement to have your app be Vista Certified I think. If you are getting that exception though, I *very* strongly suspect that your DLL that is being loaded twice is different somehow. I know you THINK it is the same, but when you do come around to fixing the issue, I am sure that file not being the same will be involved in the solution...
JasonRShaver
A: 

The tool you need is the the Fusion Log Viewer. It will tell you the exact steps the CLR took when attempting to locate the correct assembly to load.