Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.TypeLoadException : Could not load type 'Castle.Core.Internal.CollectionExtensions' from assembly 'Castle.Core, Version=5.0.0.0 after updating to Moq 4.18.4 #1320

Closed
Saibamen opened this issue Jan 2, 2023 · 7 comments

Comments

@Saibamen
Copy link
Contributor

Saibamen commented Jan 2, 2023

System.TypeLoadException : Could not load type 'Castle.Core.Internal.CollectionExtensions' from assembly 'Castle.Core, Version=5.0.0.0 after updating from Moq 4.18.3 to Moq 4.18.4

@stakx
Copy link
Contributor

stakx commented Jan 2, 2023

Can you provide a minimal but complete project that reproduces the exception you're reporting? Otherwise there's nothing we can do here.

@stakx
Copy link
Contributor

stakx commented Jan 2, 2023

Actually, never mind. This cannot be caused by Moq. My guess is that you have some other dependency installed that relies on Castle.Core v4 (possibly Windsor), and your updating Moq now forces v5 of that library. I suggest you either update those other dependencies, or you downgrade Moq.

@stakx stakx closed this as completed Jan 2, 2023
@Saibamen
Copy link
Contributor Author

Saibamen commented Jan 2, 2023

Sorry, it has nothing to do with Moq

In my EFCore project, I used IsNullOrEmpty extension for dictionary from Castle.Core.Internal namespace (https://github.com/castleproject/Core/blob/v4.4.1/src/Castle.Core/Core/Internal/CollectionExtensions.cs).
I changed it to Microsoft.IdentityModel.Tokens namespace

@Saibamen Saibamen closed this as completed Jan 2, 2023
@MelGrubb
Copy link

It looks like, even though we don't have a direct reference to Castle.Core.Internal in our own project, ReSharper picked up on the transitive reference and "helped" add the reference to enable a call to IsNullOrEmpty at some point in our history.

The really bizarre thing is that the code breaks at the point before it calls the method with the IsNullOrEmpty in it. It's somehow psychic. We have no problem compiling the code, but at runtime it breaks when you mention the code with the IsNullOrEmpty call in it. It never even enters the method itself. I put a breakpoint in the method before it calls IsNullOrEmpty, and the method is never even entered. It's spooky. Replacing the IsNullOrEmpty call with Foos?.Any() == true accomplishes the same thing, but eliminates the error.

This is some voodoo here. I'm going to just walk away.

@stakx
Copy link
Contributor

stakx commented Apr 25, 2023

@MelGrubb, I'm guessing that this could be just-in-time (JIT) compilation at work. The following explanation may be somewhat inaccurate but maybe it aids your understanding nevertheless: .NET compiles methods to assembly code the first time it encounters them. That is, say you have a method M that calls method X, which during the execution of your program has never been called before. When it encounters a call instruction in method M for method X, it needs to compile X before X can actually run. And if X's bytecode contains a reference to any type or type member that cannot be resolved (say, the IsNullOrEmpty thingy you mention... e.g. due to the referenced assembly missing), then compilation of X cannot complete and X cannot be called at all, so your breakpoint will never be hit because execution gets stuck in M.

@MelGrubb
Copy link

Since the class that the problem occurs in has quite definitely been compiled by this point, and has been used throughout the test, I would think it had been compiled already. I was unaware that it would compile it piecemeal like that. Still, if Castle.Core hid the IsNullOrEmpty method between v4 and v5, I ought to be getting a compilation error, shouldn't I? If that method isn't visible anymore, then Intellisense shouldn't be suggesting it.

The weird part is that the error would happen in the code calling my method and not in the method itself. It does smell like some kind of JIT issue, and my only guess at this point is that somehow I have a v4 Castle.Core "visible" when writing the code that gets replaced by a v5 at runtime. It's the only explanation that makes sense to me.

Anyway, I've just dropped in my own IsNullOrEmpty extension in, and everything is back to normal again. Thanks for the follow-up.

@justmeeee
Copy link

Had the same issue.
Interestingly IsNullOrEmpty of type IEnumerable was used on a string, which shouldn't be possible at all?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants