Browse Source

Localization improvements.

pull/395/head
Halil ibrahim Kalkan 8 years ago
parent
commit
a1577656b5
  1. 51
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs
  2. 21
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs
  3. 41
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceExtensions.cs
  4. 22
      framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs

51
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs

@ -15,7 +15,7 @@ namespace Volo.Abp.Localization
private readonly AbpLocalizationOptions _abpLocalizationOptions;
private readonly IServiceProvider _serviceProvider;
private readonly ConcurrentDictionary<Type, AbpDictionaryBasedStringLocalizer> _localizerCache;
private readonly ConcurrentDictionary<Type, StringLocalizerCacheItem> _localizerCache;
//TODO: It's better to use decorator pattern for IStringLocalizerFactory instead of getting ResourceManagerStringLocalizerFactory as a dependency.
public AbpStringLocalizerFactory(
@ -27,27 +27,48 @@ namespace Volo.Abp.Localization
_serviceProvider = serviceProvider;
_abpLocalizationOptions = abpLocalizationOptions.Value;
_localizerCache = new ConcurrentDictionary<Type, AbpDictionaryBasedStringLocalizer>();
_localizerCache = new ConcurrentDictionary<Type, StringLocalizerCacheItem>();
}
public virtual IStringLocalizer Create(Type resourceType)
{
var localizationResource = _abpLocalizationOptions.Resources.GetOrDefault(resourceType);
if (localizationResource == null)
var resource = _abpLocalizationOptions.Resources.GetOrDefault(resourceType);
if (resource == null)
{
return _innerFactory.Create(resourceType);
}
return _localizerCache.GetOrAdd(resourceType, _ => CreateAbpStringLocalizer(localizationResource));
return _localizerCache.GetOrAdd(
resourceType,
_ => CreateStringLocalizerCacheItem(resource)
).Localizer;
}
private AbpDictionaryBasedStringLocalizer CreateAbpStringLocalizer(LocalizationResource resource)
private StringLocalizerCacheItem CreateStringLocalizerCacheItem(LocalizationResource resource)
{
resource.Initialize(_serviceProvider); //TODO: Use CreateScope?
using (var scope = _serviceProvider.CreateScope())
{
resource.FillDictionaries(scope.ServiceProvider);
}
if (!resource.RegisteredToUpdate)
{
resource.RegisteredToUpdate = true;
foreach (var contributor in resource.Contributors)
{
contributor.Updated += (sender, args) =>
{
_localizerCache.TryRemove(resource.ResourceType, out _);
};
}
}
return new AbpDictionaryBasedStringLocalizer(
resource,
resource.BaseResourceTypes.Select(Create).ToList()
return new StringLocalizerCacheItem(
new AbpDictionaryBasedStringLocalizer(
resource,
resource.BaseResourceTypes.Select(Create).ToList()
)
);
}
@ -63,5 +84,15 @@ namespace Volo.Abp.Localization
services.Replace(ServiceDescriptor.Singleton<IStringLocalizerFactory, AbpStringLocalizerFactory>());
services.AddSingleton<ResourceManagerStringLocalizerFactory>();
}
private class StringLocalizerCacheItem
{
public AbpDictionaryBasedStringLocalizer Localizer { get; }
public StringLocalizerCacheItem(AbpDictionaryBasedStringLocalizer localizer)
{
Localizer = localizer;
}
}
}
}

21
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs

@ -25,6 +25,10 @@ namespace Volo.Abp.Localization
[NotNull]
public List<Type> BaseResourceTypes { get; }
public EventHandler Updated;
internal bool RegisteredToUpdate { get; set; }
public LocalizationResource(
[NotNull] Type resourceType,
[CanBeNull] string defaultCultureName = null,
@ -46,25 +50,12 @@ namespace Volo.Abp.Localization
AddBaseResourceTypes();
}
public virtual void Initialize(IServiceProvider serviceProvider)
public virtual void FillDictionaries(IServiceProvider serviceProvider)
{
var context = new LocalizationResourceInitializationContext(this, serviceProvider);
Dictionaries.Clear();
InitializeContributors(context);
foreach (var contributor in Contributors)
{
contributor.Updated += (sender, args) =>
{
Dictionaries.Clear();
InitializeContributors(context);
};
}
}
var context = new LocalizationResourceInitializationContext(this, serviceProvider);
protected virtual void InitializeContributors(LocalizationResourceInitializationContext context)
{
foreach (var contributor in Contributors)
{
foreach (var dictionary in contributor.GetDictionaries(context))

41
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceExtensions.cs

@ -35,46 +35,5 @@ namespace Volo.Abp.Localization
return localizationResource;
}
//public static LocalizationResource AddVirtualJson<TResource>(
// [NotNull] this LocalizationResourceDictionary resourceDictionary,
// [CanBeNull] string defaultCultureName,
// [NotNull] string virtualPath)
//{
// Check.NotNull(resourceDictionary, nameof(resourceDictionary));
// Check.NotNull(virtualPath, nameof(virtualPath));
// return resourceDictionary
// .Add<TResource>(defaultCultureName)
// .AddVirtualJson(virtualPath);
//}
//public static LocalizationResource ExtendWithVirtualJson<TResource>(
// [NotNull] this LocalizationResourceDictionary resourceDictionary,
// [NotNull] string virtualPath)
//{
// Check.NotNull(resourceDictionary, nameof(resourceDictionary));
// return resourceDictionary
// .Get<TResource>()
// .AddVirtualJson(virtualPath);
//}
//public static LocalizationResource AddBaseTypes<TResource>(
// [NotNull] this LocalizationResourceDictionary resourceDictionary,
// [NotNull] params Type[] types)
//{
// Check.NotNull(resourceDictionary, nameof(resourceDictionary));
// Check.NotNull(types, nameof(types));
// var localizationResource = resourceDictionary.Get<TResource>();
// foreach (var type in types)
// {
// localizationResource.BaseResourceTypes.AddIfNotContains(type);
// }
// return localizationResource;
//}
}
}

22
framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs

@ -15,10 +15,11 @@ namespace Microsoft.Extensions.DependencyInjection
{
MySingletonService singletonService;
MyEmptyTransientService emptyTransientService;
MyTransientService1 transientService1;
using (var scope = ServiceProvider.CreateScope())
{
var transientService1 = scope.ServiceProvider.GetRequiredService<MyTransientService1>();
transientService1 = scope.ServiceProvider.GetRequiredService<MyTransientService1>();
emptyTransientService = scope.ServiceProvider.GetRequiredService<MyEmptyTransientService>();
transientService1.DoIt();
@ -26,13 +27,20 @@ namespace Microsoft.Extensions.DependencyInjection
singletonService = transientService1.SingletonService;
singletonService.TransientInstances.Count.ShouldBe(2);
transientService1.TransientInstances.Count.ShouldBe(2);
transientService1.TransientInstances.ForEach(ts => ts.IsDisposed.ShouldBeFalse());
}
Assert.Equal(singletonService, GetRequiredService<MySingletonService>());
singletonService.TransientInstances.Count.ShouldBe(2);
singletonService.ResolveTransient();
singletonService.TransientInstances.Count.ShouldBe(3);
singletonService.TransientInstances.ForEach(ts => ts.IsDisposed.ShouldBeFalse());
transientService1.TransientInstances.ForEach(ts => ts.IsDisposed.ShouldBeTrue());
emptyTransientService.IsDisposed.ShouldBeTrue();
}
@ -77,15 +85,23 @@ namespace Microsoft.Extensions.DependencyInjection
public class MyTransientService1 : ITransientDependency
{
public MySingletonService SingletonService { get; }
public IServiceProvider ServiceProvider { get; }
public List<MyEmptyTransientService> TransientInstances { get; }
public MyTransientService1(MySingletonService singletonService)
public MyTransientService1(MySingletonService singletonService, IServiceProvider serviceProvider)
{
SingletonService = singletonService;
ServiceProvider = serviceProvider;
TransientInstances = new List<MyEmptyTransientService>();
}
public void DoIt()
{
SingletonService.ResolveTransient();
TransientInstances.Add(
ServiceProvider.GetRequiredService<MyEmptyTransientService>()
);
}
}

Loading…
Cancel
Save