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); }
/// <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); }