dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.07k stars 2.03k forks source link

ReflectionTypeLoadException when loading my Grain, resolved with weird typeof #2840

Closed shlomiwNG closed 7 years ago

shlomiwNG commented 7 years ago

Hi,

I get the following exception:

[2017-03-12 18:36:24.434 GMT     1  WARNING 101723  CodeGenerator   127.0.0.1:11111]    AssemblyLoader encountered an exception loading types from assembly 'NG.Server.Game, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null': System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeAssembly.get_DefinedTypes()
   at Orleans.Runtime.TypeUtils.GetDefinedTypes(Assembly assembly, Logger logger)   
Exc level 0: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeAssembly.get_DefinedTypes()
   at Orleans.Runtime.TypeUtils.GetDefinedTypes(Assembly assembly, Logger logger)
Exc level 1: System.TypeLoadException: Could not load type 'NG.Server.Game.Player.PlayerGrain' from assembly 'NG.Server.Game, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

And I can't access the PlayerGrain.

But if I add in the InitSilo method: var t = typeof(PlayerGrain);

It's green again and I can access the PlayerGrain normally. Do you have any idea why?

ReubenBond commented 7 years ago

@shlomiw7 Here's what I believe is happening:

I'll improve logging and determine if we can avoid these exceptions.

Does this exception stop the silo from starting and prevent you from accessing PlayerGrain?

Would you also mind posting the full stack trace?

shlomiwNG commented 7 years ago

Thanks @ReubenBond, I since then continued developing, I tried again to remove this 'typeof' workaround, and now I can't reproduce it.

I didn't have much more details in the exception before, and I couldn't catch the logs of the 'LoaderExceptions' (see the exception details: 'Retrieve the LoaderExceptions property for more information'). It would be helpful if you'll add this logs to better understand.

If it happens again, I'll post the details here.

Thanks again!

p.s. we're writing a multiplayer game with Orleans powered backend and I'm enjoying every moment using your great framework, good job! As a startup, we had a debate choosing between Java and C#.. I'm so glad we ended up with C# and Orleans :)

shlomiwNG commented 7 years ago

Does this exception stop the silo from starting and prevent you from accessing PlayerGrain?

It didn't stop the silo but I couldn't access the PlayerGrain.

ReubenBond commented 7 years ago

Hi @shlomiw7, I opened a PR to add more logging, including the details of the exception

shlomiwNG commented 7 years ago

Many thanks! if I manage to reproduce it, I'll check it out.

jdom commented 7 years ago

@ReubenBond, a small clarification:

The silo enumerates all types whenever an assembly is loaded. When a type is enumerated, its static initializer is executed, which requires that all types directly referenced by that type are loaded. Hence the assembly for each of those types must be loaded. This is done automatically. When an assembly is loaded under the ReflectionOnly context (as is used in some parts of silo initialization), it is not able to implicitly load other assemblies.

That is actually the main difference with ReflectionOnlyLoad, when you enumerate and explore the defined types, no static constructor is executed (not even the attributes, which is why you have to compare them by name).

The type enumeration therefore fails at this point.

ReubenBond commented 7 years ago

@jdom I missed that, the latter part seems to be correct, though - that all types referenced in metadata are loaded

ReubenBond commented 7 years ago

We've made an improvement to make debugging these issues easier. If this issue is encountered again, please re-open this issue and we can work through it.

shlomiw commented 7 years ago

Great thanks a lot!

Arshia001 commented 6 years ago

I'm having the same issue, if it's still unresolved and there's any info I can provide (other than that I'm having the exact same issue with the exact same output), please tell me. One thing I can tell you is that the LoaderExceptions on the TypeLoadException has only one entry which reads System.Exception: Failed to load type xxx, which is not very helpful.

Arshia001 commented 6 years ago

Oh, and it also happens inside a client when Orleans tries to run CodeGen for the type (which is different from the type in the silo), and that can also be resolved by referencing the type beforehand. Same error, same output, same everything.

ReubenBond commented 6 years ago

@Arshia001 which version of Orleans are you using?

Arshia001 commented 6 years ago

@ReubenBond the official build of version 1.5.3 from NuGet.

ReubenBond commented 6 years ago

I believe this issue wont occur in 2.0, since all assembly loading is explicit and occurs before we look for assembly metadata.

My recommendation for 1.5.x is to explicitly load assemblies before starting the silo/client.