private static bool GetCachedCanAssign(object input, Type source, Type target)
        {
            var key = new CompositeTypeTypeKey(source, target);

            if (AssignableTypeCache.TryGetValue(key, out bool canConvert))
            {
                return(canConvert);
            }

            // "object is" is faster than "Type.IsAssignableFrom.
            // We can use it to very quickly determine whether true/false
            if (input is IConvertible && target.IsAssignableFrom(source))
            {
                return(AssignableTypeCache[key] = true);
            }

            return(AssignableTypeCache[key] = false);
        }
        private static TypeConverter GetCachedTargetTypeConverter(Type source, Type target)
        {
            var key = new CompositeTypeTypeKey(source, target);

            if (DestinationTypeConverterCache.TryGetValue(key, out TypeConverter typeConverter))
            {
                return(typeConverter);
            }

            TypeConverter converter = TypeDescriptor.GetConverter(target);

            if (converter.CanConvertFrom(source))
            {
                return(DestinationTypeConverterCache[key] = converter);
            }

            return(DestinationTypeConverterCache[key] = null);
        }
        public bool GetCachedCanAssignNoFactory()
        {
            // This method is 10% faster
            var  key = new CompositeTypeTypeKey(source, target);
            bool canConvert;

            if (AssignableTypeCache.TryGetValue(key, out canConvert))
            {
                return(canConvert);
            }

            // "is" is faster than "IsAssignableFrom"
            if (input is IConvertible && target.IsAssignableFrom(source))
            {
                return(AssignableTypeCache[key] = true);
            }

            return(AssignableTypeCache[key] = false);
        }
示例#4
0
        private IEnumerable <Type> GetTypesInternalLocked(
            Type baseType, Type attributeType,
            Func <IEnumerable <Type> > finder,
            string action,
            bool cache)
        {
            // check if the TypeList already exists, if so return it, if not we'll create it
            var      tobject  = typeof(object); // CompositeTypeTypeKey does not support null values
            var      listKey  = new CompositeTypeTypeKey(baseType ?? tobject, attributeType ?? tobject);
            TypeList typeList = null;

            if (cache)
            {
                _types.TryGetValue(listKey, out typeList); // else null
            }
            // if caching and found, return
            if (typeList != null)
            {
                // need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505
                _logger.Debug <TypeLoader>("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType));
                return(typeList.Types);
            }

            // else proceed,
            typeList = new TypeList(baseType, attributeType);

            var typesListFilePath = GetTypesListFilePath();
            var scan = RequiresRescanning || File.Exists(typesListFilePath) == false;

            if (scan)
            {
                // either we have to rescan, or we could not find the cache file:
                // report (only once) and scan and update the cache file
                if (_reportedChange == false)
                {
                    _logger.Debug <TypeLoader>("Assemblies changes detected, need to rescan everything.");
                    _reportedChange = true;
                }
            }

            if (scan == false)
            {
                // if we don't have to scan, try the cache
                var cacheResult = TryGetCached(baseType, attributeType);

                // here we need to identify if the CachedTypeNotFoundInFile was the exception, if it was then we need to re-scan
                // in some cases the type will not have been scanned for on application startup, but the assemblies haven't changed
                // so in this instance there will never be a result.
                if (cacheResult.Exception is CachedTypeNotFoundInFileException || cacheResult.Success == false)
                {
                    _logger.Debug <TypeLoader>("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType));
                    scan = true;
                }
                else
                {
                    // successfully retrieved types from the file cache: load
                    foreach (var type in cacheResult.Result)
                    {
                        var resolvedType = TypeFinder.GetTypeByName(type);
                        if (resolvedType != null)
                        {
                            typeList.Add(resolvedType);
                        }
                        else
                        {
                            // in case of any exception, we have to exit, and revert to scanning
                            _logger.Warn <TypeLoader>("Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type);
                            scan = true;
                            break;
                        }
                    }

                    if (scan == false)
                    {
                        _logger.Debug <TypeLoader>("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType));
                    }
                }
            }

            if (scan)
            {
                // either we had to scan, or we could not get the types from the cache file - scan now
                _logger.Debug <TypeLoader>("Getting {TypeName}: " + action + ".", GetName(baseType, attributeType));

                foreach (var t in finder())
                {
                    typeList.Add(t);
                }
            }

            // if we are to cache the results, do so
            if (cache)
            {
                var added = _types.ContainsKey(listKey) == false;
                if (added)
                {
                    _types[listKey] = typeList;
                    //if we are scanning then update the cache file
                    if (scan)
                    {
                        UpdateCache();
                    }
                }

                _logger.Debug <TypeLoader>("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant());
            }
            else
            {
                _logger.Debug <TypeLoader>("Got {TypeName}.", GetName(baseType, attributeType));
            }

            return(typeList.Types);
        }