Make the generic IStringLocalizer interface covariant (dotnet/extensions#1117)

Make the generic IStringLocalizer interface covariant
\n\nCommit migrated from 90020a9608
This commit is contained in:
Kévin Chalet 2019-03-08 00:42:29 +01:00 committed by Ryan Brandenburg
parent d5a386b0a9
commit 3e9a592422
3 changed files with 162 additions and 3 deletions

View File

@ -16,7 +16,7 @@ namespace Microsoft.Extensions.Localization
Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location);
Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource);
}
public partial interface IStringLocalizer<T> : Microsoft.Extensions.Localization.IStringLocalizer
public partial interface IStringLocalizer<out T> : Microsoft.Extensions.Localization.IStringLocalizer
{
}
public partial class LocalizedString

View File

@ -7,8 +7,8 @@ namespace Microsoft.Extensions.Localization
/// Represents an <see cref="IStringLocalizer"/> that provides strings for <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The <see cref="System.Type"/> to provide strings for.</typeparam>
public interface IStringLocalizer<T> : IStringLocalizer
public interface IStringLocalizer<out T> : IStringLocalizer
{
}
}
}

View File

@ -0,0 +1,159 @@
// 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 Moq;
using Xunit;
namespace Microsoft.Extensions.Localization
{
public class StringLocalizerOfTTest
{
[Fact]
public void Constructor_ThrowsAnExceptionForNullFactory()
{
// Arrange, act and assert
var exception = Assert.Throws<ArgumentNullException>(
() => new StringLocalizer<object>(factory: null));
Assert.Equal("factory", exception.ParamName);
}
[Fact]
public void Constructor_ResolvesLocalizerFromFactory()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
// Act
_ = new StringLocalizer<object>(factory.Object);
// Assert
factory.Verify(mock => mock.Create(typeof(object)), Times.Once());
}
[Fact]
public void WithCulture_InvokesWithCultureFromInnerLocalizer()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act
#pragma warning disable CS0618
localizer.WithCulture(CultureInfo.GetCultureInfo("fr-FR"));
#pragma warning restore CS0618
// Assert
#pragma warning disable CS0618
innerLocalizer.Verify(mock => mock.WithCulture(CultureInfo.GetCultureInfo("fr-FR")), Times.Once());
#pragma warning restore CS0618
}
[Fact]
public void Indexer_ThrowsAnExceptionForNullName()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null]);
Assert.Equal("name", exception.ParamName);
}
[Fact]
public void Indexer_InvokesIndexerFromInnerLocalizer()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act
_ = localizer["Hello world"];
// Assert
innerLocalizer.Verify(mock => mock["Hello world"], Times.Once());
}
[Fact]
public void Indexer_ThrowsAnExceptionForNullName_WithArguments()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null]);
Assert.Equal("name", exception.ParamName);
}
[Fact]
public void Indexer_InvokesIndexerFromInnerLocalizer_WithArguments()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act
_ = localizer["Welcome, {0}", "Bob"];
// Assert
innerLocalizer.Verify(mock => mock["Welcome, {0}", "Bob"], Times.Once());
}
[Fact]
public void GetAllStrings_InvokesGetAllStringsFromInnerLocalizer()
{
// Arrange
var factory = new Mock<IStringLocalizerFactory>();
var innerLocalizer = new Mock<IStringLocalizer>();
factory.Setup(mock => mock.Create(typeof(object)))
.Returns(innerLocalizer.Object);
var localizer = new StringLocalizer<object>(factory.Object);
// Act
localizer.GetAllStrings(includeParentCultures: true);
// Assert
innerLocalizer.Verify(mock => mock.GetAllStrings(true), Times.Once());
}
[Fact]
public void StringLocalizer_CanBeCastToBaseType()
{
// Arrange and act
IStringLocalizer<BaseType> localizer = new StringLocalizer<DerivedType>(Mock.Of<IStringLocalizerFactory>());
// Assert
Assert.NotNull(localizer);
}
private class BaseType { }
private class DerivedType : BaseType { }
}
}