Statics be gone!

- Cleaned up ctors of ResourceManagerStringLocalizer and ResourceManagerWithCultureStringLocalizer too
This commit is contained in:
damianedwards 2015-05-28 12:14:03 -07:00
parent 59033fed80
commit 90ca64c3dd
6 changed files with 83 additions and 39 deletions

View File

@ -0,0 +1,22 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Framework.Localization
{
/// <summary>
/// Represents a cache of string names in resources.
/// </summary>
public interface IResourceNamesCache
{
/// <summary>
/// Adds a set of resource names to the cache by using the specified function, if the name does not already exist.
/// </summary>
/// <param name="name">The resource name to add string names for.</param>
/// <param name="valueFactory">The function used to generate the string names for the resource.</param>
/// <returns>The string names for the resource.</returns>
IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory);
}
}

View File

@ -18,12 +18,10 @@ namespace Microsoft.Framework.Localization
/// </summary>
public class ResourceManagerStringLocalizer : IStringLocalizer
{
private static readonly ConcurrentDictionary<string, IList<string>> _resourceNamesCache =
new ConcurrentDictionary<string, IList<string>>();
private readonly ConcurrentDictionary<string, object> _missingManifestCache =
new ConcurrentDictionary<string, object>();
private readonly IResourceNamesCache _resourceNamesCache;
private readonly ResourceManager _resourceManager;
private readonly AssemblyWrapper _resourceAssemblyWrapper;
private readonly string _resourceBaseName;
@ -34,11 +32,13 @@ namespace Microsoft.Framework.Localization
/// <param name="resourceManager">The <see cref="System.Resources.ResourceManager"/> to read strings from.</param>
/// <param name="resourceAssembly">The <see cref="Assembly"/> that contains the strings as embedded resources.</param>
/// <param name="baseName">The base name of the embedded resource in the <see cref="Assembly"/> that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
public ResourceManagerStringLocalizer(
[NotNull] ResourceManager resourceManager,
[NotNull] Assembly resourceAssembly,
[NotNull] string baseName)
: this(resourceManager, new AssemblyWrapper(resourceAssembly), baseName)
[NotNull] string baseName,
[NotNull] IResourceNamesCache resourceNamesCache)
: this(resourceManager, new AssemblyWrapper(resourceAssembly), baseName, resourceNamesCache)
{
}
@ -49,11 +49,13 @@ namespace Microsoft.Framework.Localization
public ResourceManagerStringLocalizer(
[NotNull] ResourceManager resourceManager,
[NotNull] AssemblyWrapper resourceAssemblyWrapper,
[NotNull] string baseName)
[NotNull] string baseName,
[NotNull] IResourceNamesCache resourceNamesCache)
{
_resourceAssemblyWrapper = resourceAssemblyWrapper;
_resourceManager = resourceManager;
_resourceBaseName = baseName;
_resourceNamesCache = resourceNamesCache;
}
/// <inheritdoc />
@ -85,10 +87,16 @@ namespace Microsoft.Framework.Localization
public IStringLocalizer WithCulture(CultureInfo culture)
{
return culture == null
? new ResourceManagerStringLocalizer(_resourceManager, _resourceAssemblyWrapper, _resourceBaseName)
: new ResourceManagerWithCultureStringLocalizer(_resourceManager,
_resourceAssemblyWrapper,
? new ResourceManagerStringLocalizer(
_resourceManager,
_resourceAssemblyWrapper.Assembly,
_resourceBaseName,
_resourceNamesCache)
: new ResourceManagerWithCultureStringLocalizer(
_resourceManager,
_resourceAssemblyWrapper.Assembly,
_resourceBaseName,
_resourceNamesCache,
culture);
}
@ -143,9 +151,6 @@ namespace Microsoft.Framework.Localization
}
}
// Internal to allow testing
internal static void ClearResourceNamesCache() => _resourceNamesCache.Clear();
private IEnumerable<string> GetResourceNamesFromCultureHierarchy(CultureInfo startingCulture)
{
var currentCulture = startingCulture;

View File

@ -5,7 +5,6 @@ using System;
using System.Reflection;
using System.Resources;
using Microsoft.Framework.Internal;
using Microsoft.Framework.Localization.Internal;
using Microsoft.Framework.Runtime;
namespace Microsoft.Framework.Localization
@ -15,6 +14,8 @@ namespace Microsoft.Framework.Localization
/// </summary>
public class ResourceManagerStringLocalizerFactory : IStringLocalizerFactory
{
private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache();
private readonly IApplicationEnvironment _applicationEnvironment;
/// <summary>
@ -35,9 +36,13 @@ namespace Microsoft.Framework.Localization
public IStringLocalizer Create([NotNull] Type resourceSource)
{
var typeInfo = resourceSource.GetTypeInfo();
var assembly = new AssemblyWrapper(typeInfo.Assembly);
var assembly = typeInfo.Assembly;
var baseName = typeInfo.FullName;
return new ResourceManagerStringLocalizer(new ResourceManager(resourceSource), assembly, baseName);
return new ResourceManagerStringLocalizer(
new ResourceManager(resourceSource),
assembly,
baseName,
_resourceNamesCache);
}
/// <summary>
@ -52,8 +57,9 @@ namespace Microsoft.Framework.Localization
return new ResourceManagerStringLocalizer(
new ResourceManager(baseName, assembly),
new AssemblyWrapper(assembly),
baseName);
assembly,
baseName,
_resourceNamesCache);
}
}
}

View File

@ -6,7 +6,6 @@ using System.Globalization;
using System.Reflection;
using System.Resources;
using Microsoft.Framework.Internal;
using Microsoft.Framework.Localization.Internal;
namespace Microsoft.Framework.Localization
{
@ -24,26 +23,15 @@ namespace Microsoft.Framework.Localization
/// <param name="resourceManager">The <see cref="System.Resources.ResourceManager"/> to read strings from.</param>
/// <param name="resourceAssembly">The <see cref="Assembly"/> that contains the strings as embedded resources.</param>
/// <param name="baseName">The base name of the embedded resource in the <see cref="Assembly"/> that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
/// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param>
public ResourceManagerWithCultureStringLocalizer(
[NotNull] ResourceManager resourceManager,
[NotNull] Assembly assembly,
[NotNull] Assembly resourceAssembly,
[NotNull] string baseName,
[NotNull] IResourceNamesCache resourceNamesCache,
[NotNull] CultureInfo culture)
: base(resourceManager, assembly, baseName)
{
_culture = culture;
}
/// <summary>
/// Intended for testing purposes only.
/// </summary>
public ResourceManagerWithCultureStringLocalizer(
[NotNull] ResourceManager resourceManager,
[NotNull] AssemblyWrapper assemblyWrapper,
[NotNull] string baseName,
[NotNull] CultureInfo culture)
: base(resourceManager, assemblyWrapper, baseName)
: base(resourceManager, resourceAssembly, baseName, resourceNamesCache)
{
_culture = culture;
}

View File

@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Microsoft.Framework.Localization
{
/// <summary>
/// An implementation of <see cref="IResourceNamesCache"/> backed by a <see cref="ConcurrentDictionary{TKey, TValue}"/>.
/// </summary>
public class ResourceNamesCache : IResourceNamesCache
{
private readonly ConcurrentDictionary<string, IList<string>> _cache = new ConcurrentDictionary<string, IList<string>>();
/// <inheritdoc />
public IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory)
{
return _cache.GetOrAdd(name, valueFactory);
}
}
}

View File

@ -17,12 +17,12 @@ namespace Microsoft.Framework.Localization.Test
public void EnumeratorCachesCultureWalkForSameAssembly()
{
// Arrange
ResourceManagerStringLocalizer.ClearResourceNamesCache();
var resourceNamesCache = new ResourceNamesCache();
var baseName = "test";
var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var localizer1 = new ResourceManagerStringLocalizer(resourceManager, resourceAssembly, baseName);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager, resourceAssembly, baseName);
var localizer1 = new ResourceManagerStringLocalizer(resourceManager, resourceAssembly, baseName, resourceNamesCache);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager, resourceAssembly, baseName, resourceNamesCache);
// Act
for (int i = 0; i < 5; i++)
@ -40,14 +40,14 @@ namespace Microsoft.Framework.Localization.Test
public void EnumeratorCacheIsScopedByAssembly()
{
// Arrange
ResourceManagerStringLocalizer.ClearResourceNamesCache();
var resourceNamesCache = new ResourceNamesCache();
var baseName = "test";
var resourceAssembly1 = new TestAssemblyWrapper("Assembly1");
var resourceAssembly2 = new TestAssemblyWrapper("Assembly2");
var resourceManager1 = new TestResourceManager(baseName, resourceAssembly1.Assembly);
var resourceManager2 = new TestResourceManager(baseName, resourceAssembly2.Assembly);
var localizer1 = new ResourceManagerStringLocalizer(resourceManager1, resourceAssembly1, baseName);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager2, resourceAssembly2, baseName);
var localizer1 = new ResourceManagerStringLocalizer(resourceManager1, resourceAssembly1, baseName, resourceNamesCache);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager2, resourceAssembly2, baseName, resourceNamesCache);
// Act
localizer1.ToList();