Error happening frequently in the background

May 31, 2012 at 8:11 AM

Hello

With the succesful migration to the latest Catel build, we've been digging and it came to our attention that some errors happen in the background (we only saw it after enabling some extra "throw error" options in VS).

There is one specific error that happens alot, it has to do with the assembly:

Could not load file or assembly '**assemblyName**, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest. (Exception from HRESULT: 0x80131053)

When looking at the call stack, always get's thrown in the same method:

Catel.Core!Catel.TypeHelper.GetType(string typeName, string assemblyName) + 0x163 bytes

This error doesn't make the app hang or crash, but I'm trying to decrease the errors that are happening, especially in this case where it's thrown 20-30 times per navigation. So this happens every time we navigate, so maybe it can help to show which method is the first one of Catel gets called in the call stack:

Catel.MVVM!Catel.MVVM.ViewLocator.ResolveView(System.Type viewModelType) + 0x78 bytes

Do you have any idea what can be causing this behavior?

Thanks in advance.

Coordinator
May 31, 2012 at 2:45 PM

Yes, this is completely normal. To speed up performance for reflection, Catel initializes all types the first time a type is required. It loops through all types in the AppDomain and this always causes TypeLoadExceptions.

The exception is correctly caught, and the types that *were* loaded correctly are still added to the internal dictionaries. This way, the next time a type is required, it has no reflection overhead.

It is always recommend to call this manually at startup. Better have a few seconds more startup time, than a stuttering app the first time it is used (but that is always up to the developer):

TypeHelper.InitializeTypes(false);

 

Next, the application tries to load the types from the type helper based on resolved naming convention. If a naming convention cannot be found, this error occurs. Maybe I should change this code to use the cached stuff.

Coordinator
May 31, 2012 at 2:52 PM

It already uses the cache, so that shouldn't be a problem. Can you give the exact load exception? Then I can handle it correctly based on its exception type.

May 31, 2012 at 2:57 PM

It's a FileLoadException we are experiencing. I guess they get caught as well, cause the code executes everything as expected, it's just when we turn on extra error catching in the options, that we hit FileLoadExceptions.

 

In the meanwhile, I also tried adding Typhelper.InitializeType(false) , addedin my bootstrapper so it certainly called at the beginning of the app, but the app starts as fast as always and there's still a little freeze/waiting time when a viewmodel is first loaded. The second time we go to a registered viewmodel, it's practically instant. Is there any way to shorten to first load time?

Coordinator
May 31, 2012 at 3:05 PM

Using prism? Then the type initializer works like this:

1) Initialize appdomain (very empty at startup)

2) Next time a type is not found, it checks the assembly and adds the type of that assembly (thus lazy loading of assembly types).

 

This is probably happening to you. Then you have to either accept this behavior or call TypeHelper.InitializeType(false, yourAssemblyName) every time a module is loaded (then it will only load that specific assembly).

May 31, 2012 at 3:18 PM

yes, we are using the regions from prism (for majority of the navigation) and therefore have a bootstrapper class.

So what exactly do you mean with modules: you mean the viewmodels, ...?

And the loading stands for navigating to a viewmodel and registering/loading it?

Coordinator
May 31, 2012 at 3:20 PM
Edited May 31, 2012 at 3:21 PM

No, you probably load modules on the fly, but this is done *after* the bootstrapper. Therefore, TypeHelper.InitializeTypes at app startup has no effect. I am really talking about the prism modules. If you are not using that, call the TypeHelper.InitializeTypes after the IoC container has been created.

 

Btw. Catel always has to resolve a viewmodel => view or vice versa once. Then it caches that result so that's even faster. Maybe it's because the naming conventions do not match, Catel tries to lazy load a non-existing assembly.