private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
{
var assembly = args.LoadedAssembly;
if (ShouldIgnoreAssembly(assembly))
{
Log.Debug("Reflection '{0}' is on the list to be ignored (for example, ReflectionOnly is true), cannot use this assembly", assembly.FullName);
return;
}
// Prevent deadlocks by checking whether this assembly might be loaded from a different thread:
// 1)
if (Monitor.TryEnter(_lockObject))
{
var assemblyName = assembly.FullName;
if (!_loadedAssemblies.Contains(assemblyName))
{
// Fix for CTL-543
// General idea of fix - prevent to call GetTypes() method recursively.
// When type load will fail CLR will try to localize message, and on
// some OS's (i suspect on non english Windows and .NET) will try to load
// satellite assembly with localization, Catel will get event before CLR
// finishes handling process. Catel will try to initialize types. When another
// type won't load CLR will detect that it still trying to handle previous
// type load problem and will crash whole process.
if (_isAlreadyInLoadingEvent)
{
// Will be proceed in finally block
_onAssemblyLoadedDelayQueue.Enqueue(assembly);
}
else
{
try
{
_isAlreadyInLoadingEvent = true;
InitializeTypes(assembly);
}
finally
{
while (_onAssemblyLoadedDelayQueue.Count > 0)
{
var delayedAssembly = _onAssemblyLoadedDelayQueue.Dequeue();
// Copy/pasted assembly processing behaviour, like types were processed without any delay
InitializeTypes(delayedAssembly);
}
_isAlreadyInLoadingEvent = false;
}
}
}
Monitor.Exit(_lockObject);
}
else
{
lock (_threadSafeAssemblyQueue)
{
_threadSafeAssemblyQueue.Enqueue(assembly);
}
}
// Important to do outside of the lock
var handler = AssemblyLoaded;
if (handler != null)
{
var types = GetTypesOfAssembly(assembly);
var eventArgs = new AssemblyLoadedEventArgs(assembly, types);
handler(null, eventArgs);
}
}
#endif