Example #1
0
        public bool ShouldScan(Type target)
        {
            if(target.BaseType == typeof(Enum))
                _actualScanner = new LocalizedEnumTypeScanner();
            else
                _actualScanner = new LocalizedResourceTypeScanner();

            return true;
        }
        public bool ShouldScan(Type target)
        {
            if (target.BaseType == typeof(Enum))
            {
                _actualScanner = new LocalizedEnumTypeScanner();
            }
            else
            {
                _actualScanner = new LocalizedResourceTypeScanner();
            }

            return(true);
        }
        public bool ShouldScan(Type target)
        {
            if (target.BaseType == typeof(Enum))
            {
                _actualScanner = new LocalizedEnumTypeScanner(_keyBuilder, _translationBuilder);
            }
            else
            {
                _actualScanner =
                    new LocalizedResourceTypeScanner(_keyBuilder,
                                                     _oldKeyBuilder,
                                                     _state,
                                                     _configurationContext,
                                                     _translationBuilder);
            }

            return(true);
        }
        /// <summary>
        /// Scan assemblies and return discovered resources from target type
        /// </summary>
        /// <param name="target">Class to scan resources in</param>
        /// <param name="keyPrefix">Resource key prefix (if needed)</param>
        /// <param name="scanner">Which scanner to use to discover resources</param>
        /// <returns>Discovered resources from found assemblies</returns>
        public IEnumerable <DiscoveredResource> ScanResources(
            Type target,
            string keyPrefix             = null,
            IResourceTypeScanner scanner = null)
        {
            var typeScanner = scanner;

            if (scanner == null)
            {
                typeScanner = _scanners.FirstOrDefault(s => s.ShouldScan(target));
            }

            if (typeScanner == null)
            {
                return(Enumerable.Empty <DiscoveredResource>());
            }

            if (target.IsGenericParameter)
            {
                return(Enumerable.Empty <DiscoveredResource>());
            }

            var resourceKeyPrefix = typeScanner.GetResourceKeyPrefix(target, keyPrefix);

            var buffer = new List <DiscoveredResource>();

            buffer.AddRange(typeScanner.GetClassLevelResources(target, resourceKeyPrefix));
            buffer.AddRange(typeScanner.GetResources(target, resourceKeyPrefix));

            var result = buffer.Where(t => t.IsIncluded()).ToList();

            foreach (var property in buffer.Where(t => t.IsComplex()))
            {
                if (!property.IsSimpleType)
                {
                    if (property.ReturnType != typeof(object) && property.ReturnType.IsAssignableFrom(target))
                    {
                        throw new RecursiveResourceReferenceException(
                                  $"Property `{property.PropertyName}` in `{target.FullName}` has the same return type as enclosing class. This will result in StackOverflowException. Consider adding [Ignore] attribute.");
                    }

                    result.AddRange(ScanResources(property.DeclaringType, property.Key, typeScanner));
                }
            }

            // throw up if there are any duplicate resources manually registered
            var duplicateKeys = result.Where(r => r.FromResourceKeyAttribute)
                                .GroupBy(r => r.Key)
                                .Where(g => g.Count() > 1)
                                .ToList();

            if (duplicateKeys.Any())
            {
                throw new DuplicateResourceKeyException(
                          $"Duplicate keys: [{string.Join(", ", duplicateKeys.Select(g => g.Key))}]");
            }

            // we need to filter out duplicate resources (this comes from the case when the same model is used in multiple places
            // in the same parent container type. for instance: billing address and office address. both of them will be registered
            // under Address container type - twice, one via billing context - another one via office address property).
            result = result.DistinctBy(r => r.Key).ToList();

            // add scanned resources to the cache
            DiscoveredResourceCache.TryAdd(target.FullName,
                                           result.Where(r => !string.IsNullOrEmpty(r.PropertyName))
                                           .Select(r => r.PropertyName)
                                           .ToList());

            return(result);
        }
Example #5
0
        /// <summary>   Scans the resources in this collection. </summary>
        /// <exception cref="DuplicateResourceKeyException">
        ///     Thrown when a Duplicate Resource
        ///     Key error condition occurs.
        /// </exception>
        /// <exception cref="DuplicateResourceTranslationsException">
        ///     Thrown when a Duplicate Resource
        ///     Translations error condition
        ///     occurs.
        /// </exception>
        /// <param name="target">       Target for the. </param>
        /// <param name="keyPrefix">    (Optional) The key prefix. </param>
        /// <param name="scanner">      (Optional) The scanner. </param>
        /// <returns>
        ///     An enumerator that allows foreach to be used to process the resources in this collection.
        /// </returns>
        public IEnumerable <DiscoveredResource> ScanResources(Type target, string keyPrefix = null,
                                                              IResourceTypeScanner scanner  = null)
        {
            var typeScanner = scanner;

            if (scanner == null)
            {
                typeScanner = _scanners.FirstOrDefault(s => s.ShouldScan(target));
            }

            if (typeScanner == null)
            {
                return(Enumerable.Empty <DiscoveredResource>());
            }

            if (target.IsGenericParameter)
            {
                return(Enumerable.Empty <DiscoveredResource>());
            }

            var resourceKeyPrefix = typeScanner.GetResourceKeyPrefix(target, keyPrefix);

            var buffer = new List <DiscoveredResource>();

            buffer.AddRange(typeScanner.GetClassLevelResources(target, resourceKeyPrefix));
            buffer.AddRange(typeScanner.GetResources(target, resourceKeyPrefix));

            var result = buffer.Where(t =>
                                      t.IsSimpleType || t.Info == null || t.Info.GetCustomAttribute <IncludeAttribute>() != null)
                         .ToList();

            foreach (var property in buffer.Where(t => !t.IsSimpleType))
            {
                if (!property.IsSimpleType)
                {
                    result.AddRange(ScanResources(property.DeclaringType, property.Key, typeScanner));
                }
            }

            // throw up if there are any duplicate resources manually registered
            var duplicateKeys = result.Where(r => r.FromResourceKeyAttribute).GroupBy(r => r.Key)
                                .Where(g => g.Count() > 1).ToList();

            if (duplicateKeys.Any())
            {
                throw new DuplicateResourceKeyException(
                          $"Duplicate keys: [{string.Join(", ", duplicateKeys.Select(g => g.Key))}]");
            }

            // throw up if there are multiple translations for the same culture (might come from misuse of [TranslationForCulture] attribute)
            var duplicateTranslations =
                result.Where(r => r.Translations.GroupBy(t => t.Culture).Any(g => g.Count() > 1)).ToList();

            if (duplicateTranslations.Any())
            {
                throw new
                      DuplicateResourceTranslationsException(
                          $"Duplicate translations for the same culture for following resources: [{string.Join(", ", duplicateTranslations.Select(g => g.Key))}]");
            }

            // we need to filter out duplicate resources (this comes from the case when the same model is used in multiple places
            // in the same parent container type. for instance: billing address and office address. both of them will be registered
            // under Address container type - twice, one via billing context - another one via office address property).
            result = result.DistinctBy(r => r.Key).ToList();

            // add scanned resources to the cache
            DiscoveredResourceCache.TryAdd(target.FullName,
                                           result.Where(r => !string.IsNullOrEmpty(r.PropertyName)).Select(r => r.PropertyName).ToList());

            return(result);
        }