Beispiel #1
0
        /// <summary>
        /// Called when an assembly is loaded in the current <see cref="AppDomain"/>.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="AssemblyLoadEventArgs" /> instance containing the event data.</param>
        private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
        {
            var assembly = args.LoadedAssembly;

            if (assembly.ReflectionOnly)
            {
                Log.Debug("Reflection '{0}' is loaded for reflection-only, cannot use this assembly", assembly.FullName);
                return;
            }

            lock (_lockObject)
            {
                var assemblyName = assembly.FullName;
                if (_loadedAssemblies.Contains(assemblyName))
                {
                    return;
                }

                InitializeTypes(false, assembly);

                var handler = AssemblyLoaded;
                if (handler != null)
                {
                    var types     = GetTypesOfAssembly(assembly);
                    var eventArgs = new AssemblyLoadedEventArgs(assembly, types);

                    handler(null, eventArgs);
                }

                _loadedAssemblies.Add(assemblyName);
            }
        }
Beispiel #2
0
        private static void InitializeAssemblies(IEnumerable <Assembly> assemblies, bool force, bool allowMultithreadedInitialization = false)
        {
            // Important note: only allow explicit multithreaded initialization

            var listForLoadedEvent = new List <Tuple <Assembly, Type[]> >();

            lock (_lockObject)
            {
                var assembliesToRetrieve = new List <Assembly>();

                foreach (var assembly in assemblies)
                {
                    var loadedAssemblyFullName = assembly.FullName;
                    var containsLoadedAssembly = _loadedAssemblies.Contains(loadedAssemblyFullName);
                    if (!force && containsLoadedAssembly)
                    {
                        continue;
                    }

                    if (!containsLoadedAssembly)
                    {
                        _loadedAssemblies.Add(loadedAssemblyFullName);
                    }

                    if (ShouldIgnoreAssembly(assembly))
                    {
                        continue;
                    }

                    assembliesToRetrieve.Add(assembly);
                }

                var typesToAdd = GetAssemblyTypes(assembliesToRetrieve, allowMultithreadedInitialization);
                foreach (var assemblyWithTypes in typesToAdd)
                {
                    foreach (var type in assemblyWithTypes.Value)
                    {
                        InitializeType(assemblyWithTypes.Key, type);
                    }
                }

#if NET || NETCORE || NETSTANDARD
                var lateLoadedAssemblies = new List <Assembly>();

                lock (_threadSafeAssemblyQueue)
                {
                    while (_threadSafeAssemblyQueue.Count > 0)
                    {
                        var assembly = _threadSafeAssemblyQueue.Dequeue();

                        lateLoadedAssemblies.Add(assembly);
                    }
                }

                foreach (var lateLoadedAssembly in lateLoadedAssemblies)
                {
                    var tuple = Tuple.Create(lateLoadedAssembly, GetTypesOfAssembly(lateLoadedAssembly));
                    listForLoadedEvent.Add(tuple);
                }
#endif
            }

            // Calling out of lock statement, but still may happens that would be called inside of it
            var handler = AssemblyLoaded;
            if (handler != null)
            {
                foreach (var tuple in listForLoadedEvent)
                {
                    var assembly  = tuple.Item1;
                    var types     = tuple.Item2;
                    var eventArgs = new AssemblyLoadedEventArgs(assembly, types);

                    handler(null, eventArgs);
                }
            }
        }
Beispiel #3
0
        private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
        {
            var assembly = args.LoadedAssembly;

            if (ShouldIgnoreAssembly(assembly))
            {
                Log.Debug($"Reflection '{assembly.FullName}' is on the list to be ignored (for example, ReflectionOnly is true), cannot use this assembly");
                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);

                // Important to do outside of the lock
                var handler = AssemblyLoaded;
                if (handler != null)
                {
                    var eventArgs = new AssemblyLoadedEventArgs(assembly, new Lazy <IEnumerable <Type> >(() => GetTypesOfAssembly(assembly)));

                    handler(null, eventArgs);
                }
            }
            else
            {
                lock (_threadSafeAssemblyQueue)
                {
                    _threadSafeAssemblyQueue.Enqueue(assembly);
                }

                // Note: AssemblyLoaded will be invoked later when the assembly
                // is actually loaded, fixed for https://github.com/Catel/Catel/issues/1120
            }
        }
Beispiel #4
0
        /// <summary>
        /// Called when an assembly is loaded in the current <see cref="AppDomain"/>.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="AssemblyLoadEventArgs" /> instance containing the event data.</param>
        private static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
        {
            var assembly = args.LoadedAssembly;

            if (assembly.ReflectionOnly)
            {
                Log.Debug("Reflection '{0}' is loaded for reflection-only, cannot use this assembly", assembly.FullName);
                return;
            }

            InitializeTypes(false, assembly);

            var handler = AssemblyLoaded;
            if (handler != null)
            {
                var types = GetTypesOfAssembly(assembly);
                var eventArgs = new AssemblyLoadedEventArgs(assembly, types);

                handler(null, eventArgs);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Called when an assembly is loaded in the current <see cref="AppDomain"/>.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="AssemblyLoadEventArgs" /> instance containing the event data.</param>
        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);
            }
        }
Beispiel #6
0
 /// <summary>
 /// Called when the <see cref="TypeCache.AssemblyLoaded"/> event occurs.
 /// </summary>
 /// <param name="sender">The sender.</param>
 /// <param name="e">The <see cref="AssemblyLoadedEventArgs"/> instance containing the event data.</param>
 private void OnAssemblyLoaded(object sender, AssemblyLoadedEventArgs e)
 {
     ClearCache();
 }
Beispiel #7
0
 /// <summary>
 /// Called when an assembly gets loaded.
 /// </summary>
 /// <param name="sender">The sender.</param>
 /// <param name="e">The <see cref="AssemblyLoadedEventArgs"/> instance containing the event data.</param>
 private static void OnAssemblyLoaded(object sender, AssemblyLoadedEventArgs e)
 {
     lock (_lockObject)
     {
         _serviceLocatorInitializers = null;
     }
 }