Add location to LocalizedString and add logging (#331)

This commit is contained in:
Ryan Brandenburg 2017-02-24 10:54:03 -08:00 коммит произвёл GitHub
Родитель 970e2e0782
Коммит 39aa9438ab
10 изменённых файлов: 213 добавлений и 36 удалений

Просмотреть файл

@ -27,6 +27,18 @@ namespace Microsoft.Extensions.Localization
/// <param name="value">The actual string.</param>
/// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param>
public LocalizedString(string name, string value, bool resourceNotFound)
: this(name, value, resourceNotFound, searchedLocation: null)
{
}
/// <summary>
/// Creates a new <see cref="LocalizedString"/>.
/// </summary>
/// <param name="name">The name of the string in the resource it was loaded from.</param>
/// <param name="value">The actual string.</param>
/// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param>
/// <param name="searchedLocation">The location which was searched for a localization value.</param>
public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation)
{
if (name == null)
{
@ -41,6 +53,7 @@ namespace Microsoft.Extensions.Localization
Name = name;
Value = value;
ResourceNotFound = resourceNotFound;
SearchedLocation = searchedLocation;
}
public static implicit operator string(LocalizedString localizedString)
@ -63,6 +76,11 @@ namespace Microsoft.Extensions.Localization
/// </summary>
public bool ResourceNotFound { get; }
/// <summary>
/// The location which was searched for a localization value.
/// </summary>
public string SearchedLocation { get; }
/// <summary>
/// Returns the actual string.
/// </summary>

Просмотреть файл

@ -0,0 +1,27 @@
// 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.Globalization;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.Localization.Internal
{
internal static class ResourceManagerStringLocalizerLoggerExtensions
{
private static readonly Action<ILogger, string, string, CultureInfo, Exception> _searchedLocation;
static ResourceManagerStringLocalizerLoggerExtensions()
{
_searchedLocation = LoggerMessage.Define<string, string, CultureInfo>(
LogLevel.Debug,
1,
$"{nameof(ResourceManagerStringLocalizer)} searched for '{{Key}}' in '{{LocationSearched}}' with culture '{{Culture}}'.");
}
public static void SearchedLocation(this ILogger logger, string key, string searchedLocation, CultureInfo culture)
{
_searchedLocation(logger, key, searchedLocation, culture, null);
}
}
}

Просмотреть файл

@ -15,6 +15,7 @@
<ProjectReference Include="..\Microsoft.Extensions.Localization.Abstractions\Microsoft.Extensions.Localization.Abstractions.csproj" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Options" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.2.0-*" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">

Просмотреть файл

@ -8,6 +8,7 @@ using System.Globalization;
using System.Reflection;
using System.Resources;
using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.Localization
{
@ -23,6 +24,7 @@ namespace Microsoft.Extensions.Localization
private readonly ResourceManager _resourceManager;
private readonly IResourceStringProvider _resourceStringProvider;
private readonly string _resourceBaseName;
private readonly ILogger _logger;
/// <summary>
/// Creates a new <see cref="ResourceManagerStringLocalizer"/>.
@ -31,16 +33,19 @@ namespace Microsoft.Extensions.Localization
/// <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 that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
/// <param name="logger">The <see cref="ILogger"/>.</param>
public ResourceManagerStringLocalizer(
ResourceManager resourceManager,
Assembly resourceAssembly,
string baseName,
IResourceNamesCache resourceNamesCache)
IResourceNamesCache resourceNamesCache,
ILogger logger)
: this(
resourceManager,
new AssemblyWrapper(resourceAssembly),
baseName,
resourceNamesCache)
resourceNamesCache,
logger)
{
}
@ -51,12 +56,14 @@ namespace Microsoft.Extensions.Localization
ResourceManager resourceManager,
AssemblyWrapper resourceAssemblyWrapper,
string baseName,
IResourceNamesCache resourceNamesCache)
IResourceNamesCache resourceNamesCache,
ILogger logger)
: this(
resourceManager,
new AssemblyResourceStringProvider(resourceNamesCache, resourceAssemblyWrapper, baseName),
baseName,
resourceNamesCache)
resourceNamesCache,
logger)
{
}
@ -67,7 +74,8 @@ namespace Microsoft.Extensions.Localization
ResourceManager resourceManager,
IResourceStringProvider resourceStringProvider,
string baseName,
IResourceNamesCache resourceNamesCache)
IResourceNamesCache resourceNamesCache,
ILogger logger)
{
if (resourceManager == null)
{
@ -89,10 +97,16 @@ namespace Microsoft.Extensions.Localization
throw new ArgumentNullException(nameof(resourceNamesCache));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_resourceStringProvider = resourceStringProvider;
_resourceManager = resourceManager;
_resourceBaseName = baseName;
_resourceNamesCache = resourceNamesCache;
_logger = logger;
}
/// <inheritdoc />
@ -107,7 +121,7 @@ namespace Microsoft.Extensions.Localization
var value = GetStringSafely(name, null);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName);
}
}
@ -124,7 +138,7 @@ namespace Microsoft.Extensions.Localization
var format = GetStringSafely(name, null);
var value = string.Format(format ?? name, arguments);
return new LocalizedString(name, value, resourceNotFound: format == null);
return new LocalizedString(name, value, resourceNotFound: format == null, searchedLocation: _resourceBaseName);
}
}
@ -140,13 +154,15 @@ namespace Microsoft.Extensions.Localization
_resourceManager,
_resourceStringProvider,
_resourceBaseName,
_resourceNamesCache)
_resourceNamesCache,
_logger)
: new ResourceManagerWithCultureStringLocalizer(
_resourceManager,
_resourceStringProvider,
_resourceBaseName,
_resourceNamesCache,
culture);
culture,
_logger);
}
/// <inheritdoc />
@ -173,7 +189,7 @@ namespace Microsoft.Extensions.Localization
foreach (var name in resourceNames)
{
var value = GetStringSafely(name, culture);
yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName);
}
}
@ -191,7 +207,11 @@ namespace Microsoft.Extensions.Localization
throw new ArgumentNullException(nameof(name));
}
var cacheKey = $"name={name}&culture={(culture ?? CultureInfo.CurrentUICulture).Name}";
var keyCulture = culture ?? CultureInfo.CurrentUICulture;
var cacheKey = $"name={name}&culture={keyCulture.Name}";
_logger.SearchedLocation(name, _resourceBaseName, keyCulture);
if (_missingManifestCache.ContainsKey(cacheKey))
{

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Concurrent;
using System.IO;
using System.Reflection;
using System.Resources;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.Localization
@ -24,20 +25,30 @@ namespace Microsoft.Extensions.Localization
private readonly ConcurrentDictionary<string, ResourceManagerStringLocalizer> _localizerCache =
new ConcurrentDictionary<string, ResourceManagerStringLocalizer>();
private readonly string _resourcesRelativePath;
private readonly ILoggerFactory _loggerFactory;
/// <summary>
/// Creates a new <see cref="ResourceManagerStringLocalizer"/>.
/// </summary>
/// <param name="localizationOptions">The <see cref="IOptions{LocalizationOptions}"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public ResourceManagerStringLocalizerFactory(
IOptions<LocalizationOptions> localizationOptions)
IOptions<LocalizationOptions> localizationOptions,
ILoggerFactory loggerFactory)
{
if (localizationOptions == null)
{
throw new ArgumentNullException(nameof(localizationOptions));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
_resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
_loggerFactory = loggerFactory;
if (!string.IsNullOrEmpty(_resourcesRelativePath))
{
_resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
@ -180,7 +191,8 @@ namespace Microsoft.Extensions.Localization
new ResourceManager(baseName, assembly),
assembly,
baseName,
_resourceNamesCache);
_resourceNamesCache,
_loggerFactory.CreateLogger<ResourceManagerStringLocalizer>());
}
/// <summary>

Просмотреть файл

@ -7,6 +7,7 @@ using System.Globalization;
using System.Reflection;
using System.Resources;
using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.Localization
{
@ -26,13 +27,15 @@ namespace Microsoft.Extensions.Localization
/// <param name="baseName">The base name of the embedded resource 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>
/// <param name="logger">The <see cref="ILogger"/>.</param>
internal ResourceManagerWithCultureStringLocalizer(
ResourceManager resourceManager,
IResourceStringProvider resourceStringProvider,
string baseName,
IResourceNamesCache resourceNamesCache,
CultureInfo culture)
: base(resourceManager, resourceStringProvider, baseName, resourceNamesCache)
CultureInfo culture,
ILogger logger)
: base(resourceManager, resourceStringProvider, baseName, resourceNamesCache, logger)
{
if (resourceManager == null)
{
@ -70,13 +73,15 @@ namespace Microsoft.Extensions.Localization
/// <param name="baseName">The base name of the embedded resource 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>
/// <param name="logger">The <see cref="ILogger"/>.</param>
public ResourceManagerWithCultureStringLocalizer(
ResourceManager resourceManager,
Assembly resourceAssembly,
string baseName,
IResourceNamesCache resourceNamesCache,
CultureInfo culture)
: base(resourceManager, resourceAssembly, baseName, resourceNamesCache)
CultureInfo culture,
ILogger logger)
: base(resourceManager, resourceAssembly, baseName, resourceNamesCache, logger)
{
if (resourceManager == null)
{

Просмотреть файл

@ -10,6 +10,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Localization\Microsoft.AspNetCore.Localization.csproj" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.2.0-*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
<PackageReference Include="xunit" Version="2.2.0-*" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-*" />

Просмотреть файл

@ -9,7 +9,9 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Extensions.Localization\Microsoft.Extensions.Localization.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="1.2.0-*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
<PackageReference Include="Moq" Version="4.6.36-*" />
<PackageReference Include="xunit" Version="2.2.0-*" />

Просмотреть файл

@ -4,6 +4,8 @@
using System;
using System.IO;
using System.Reflection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
@ -19,8 +21,9 @@ namespace Microsoft.Extensions.Localization.Tests
public TestResourceManagerStringLocalizerFactory(
IOptions<LocalizationOptions> localizationOptions,
ResourceLocationAttribute resourceLocationAttribute)
: base(localizationOptions)
ResourceLocationAttribute resourceLocationAttribute,
ILoggerFactory loggerFactory)
: base(localizationOptions, loggerFactory)
{
_resourceLocationAttribute = resourceLocationAttribute;
}
@ -50,12 +53,15 @@ namespace Microsoft.Extensions.Localization.Tests
options.Setup(o => o.Value).Returns(locOptions);
var resourceLocationAttribute = new ResourceLocationAttribute(Path.Combine("My", "Resources"));
var loggerFactory = NullLoggerFactory.Instance;
var typeFactory = new TestResourceManagerStringLocalizerFactory(
options.Object,
resourceLocationAttribute);
resourceLocationAttribute,
loggerFactory);
var stringFactory = new TestResourceManagerStringLocalizerFactory(
options.Object,
resourceLocationAttribute);
resourceLocationAttribute,
loggerFactory);
var type = typeof(ResourceManagerStringLocalizerFactoryTest);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
@ -75,7 +81,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
// Act
var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -92,7 +99,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
// Act
var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -110,9 +118,11 @@ namespace Microsoft.Extensions.Localization.Tests
locOptions.ResourcesPath = Path.Combine("My", "Resources");
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new TestResourceManagerStringLocalizerFactory(
options.Object,
resourceLocationAttribute: null);
resourceLocationAttribute: null,
loggerFactory: loggerFactory);
// Act
factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -128,7 +138,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName;
// Act
@ -146,7 +157,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName;
// Act
@ -164,7 +176,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
var location1 = new AssemblyName(typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName).Name;
var location2 = new AssemblyName(typeof(ResourceManagerStringLocalizerFactoryTest).GetTypeInfo().Assembly.FullName).Name;
@ -184,9 +197,11 @@ namespace Microsoft.Extensions.Localization.Tests
locOptions.ResourcesPath = Path.Combine("My", "Resources");
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new TestResourceManagerStringLocalizerFactory(
options.Object,
resourceLocationAttribute: null);
resourceLocationAttribute: null,
loggerFactory: loggerFactory);
// Act
var result1 = factory.Create("baseName", location: "Microsoft.Extensions.Localization.Tests");
@ -202,7 +217,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions);
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => factory.Create("baseName", location: null));

Просмотреть файл

@ -1,13 +1,15 @@
// 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.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
namespace Microsoft.Extensions.Localization.Tests
@ -23,14 +25,17 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer1 = new ResourceManagerStringLocalizer(resourceManager,
resourceStreamManager,
baseName,
resourceNamesCache);
resourceNamesCache,
logger);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager,
resourceStreamManager,
baseName,
resourceNamesCache);
resourceNamesCache,
logger);
// Act
for (int i = 0; i < 5; i++)
@ -56,16 +61,19 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceManager2 = new TestResourceManager(baseName, resourceAssembly2.Assembly);
var resourceStreamManager1 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly1, baseName);
var resourceStreamManager2 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly2, baseName);
var logger = Logger;
var localizer1 = new ResourceManagerStringLocalizer(
resourceManager1,
resourceStreamManager1,
baseName,
resourceNamesCache);
resourceNamesCache,
logger);
var localizer2 = new ResourceManagerStringLocalizer(
resourceManager2,
resourceStreamManager2,
baseName,
resourceNamesCache);
resourceNamesCache,
logger);
// Act
localizer1.GetAllStrings().ToList();
@ -77,6 +85,57 @@ namespace Microsoft.Extensions.Localization.Tests
Assert.Equal(expectedCallCount, resourceAssembly2.GetManifestResourceStreamCallCount);
}
[Fact]
public void GetString_PopulatesSearchedLocationOnLocalizedString()
{
// Arrange
var baseName = "Resources.TestResource";
var resourceNamesCache = new ResourceNamesCache();
var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer = new ResourceManagerStringLocalizer(
resourceManager,
resourceStreamManager,
baseName,
resourceNamesCache,
logger);
// Act
var value = localizer["name"];
// Assert
Assert.Equal("Resources.TestResource", value.SearchedLocation);
}
[Fact]
[ReplaceCulture("en-US", "en-US")]
public void GetString_LogsLocationSearched()
{
// Arrange
var baseName = "Resources.TestResource";
var resourceNamesCache = new ResourceNamesCache();
var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer = new ResourceManagerStringLocalizer(
resourceManager,
resourceStreamManager,
baseName,
resourceNamesCache,
logger);
// Act
var value = localizer["a key!"];
// Assert
Assert.Equal(1, Sink.Writes.Count);
Assert.Equal("ResourceManagerStringLocalizer searched for 'a key!' in 'Resources.TestResource' with culture 'en-US'.", Sink.Writes.First().State.ToString());
}
[Theory]
[InlineData(true)]
[InlineData(false)]
@ -88,11 +147,13 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer = new ResourceManagerStringLocalizer(
resourceManager,
resourceStreamManager,
baseName,
resourceNamesCache);
resourceNamesCache,
logger);
// Act
// We have to access the result so it evaluates.
@ -113,12 +174,15 @@ namespace Microsoft.Extensions.Localization.Tests
var baseName = "testington";
var resourceAssembly = new TestAssemblyWrapper("Assembly1");
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var logger = Logger;
var localizer = new ResourceManagerWithCultureStringLocalizer(
resourceManager,
resourceAssembly.Assembly,
baseName,
resourceNamesCache,
CultureInfo.CurrentCulture);
CultureInfo.CurrentCulture,
logger);
// Act & Assert
var exception = Assert.Throws<MissingManifestResourceException>(() =>
@ -162,6 +226,17 @@ namespace Microsoft.Extensions.Localization.Tests
return result;
}
private TestSink Sink { get; } = new TestSink();
private ILogger Logger
{
get
{
return new TestLoggerFactory(Sink, true).CreateLogger<ResourceManagerStringLocalizer>();
}
}
public class TestResourceManager : ResourceManager
{
public TestResourceManager(string baseName, Assembly assembly)