ASP.NET 自定义资源提供者实现

在开发国际化ASP.NET应用程序时,资源文件的管理是一个重要的环节。本文将介绍一种模拟技术,它能够实现资源文件夹中任何资源的"自动"翻译,而无需创建和维护一系列自动翻译的resx文件。当当前文化与默认文化不同时,资源将被特定文化的标签所包围。

ASP.NET资源文件夹

ASP.NET框架处理两种类型的资源:

全局资源可以在Web应用程序的任何级别使用。resx文件必须存储在应用程序根目录的App_GlobalResources中。

本地资源仅在页面级别工作。每个网页可以定义一个与字符串资源关联的resx文件。该resx文件必须存储在与页面及其名称相同层次结构的App_LocalResources中。

有关更多信息,请参阅MSDN上的。

构建自定义ResourceProviderFactory

资源处理是通过资源提供者进行的,它允许读取特定资源。资源提供者是由ResourceProviderFactory创建的,它提供了两种方法:

CreateGlobalResourceProvider返回全局资源的资源提供者,用于类键(即App_GlobalResources中的ResX文件名称)。

CreateLocalResourceProvider返回本地资源的资源提供者,用于虚拟路径(即网页的名称)。

将实现自己的工厂,以创建自定义资源提供者。

using System.Web.Compilation; namespace MyProject.Resources { public class CulturePrefixedResourceProviderFactory : ResourceProviderFactory { public override IResourceProvider CreateGlobalResourceProvider(string classKey){ return new CulturePrefixedGlobalResXResourceProvider(classKey); } public override IResourceProvider CreateLocalResourceProvider(string virtualPath){ return new CulturePrefixedLocalResXResourceProvider(virtualPath); } } }

IResourceProvider概述

资源提供者需要实现IResourceProvider接口,该接口定义了:

ResourceReader属性,返回一个允许资源读取的读取器

GetObject方法,根据其键和文化返回资源值

本地和全局资源提供者将覆盖AbstractResXResourceProvider类,它提供了一点抽象,实现了IResourceProvider.GetObject方法,创建了翻译模拟方面。

using System.Globalization; using System.Resources; using System.Web.Compilation; namespace MyProject.Resources { public abstract class AbstractResXResourceProvider : IResourceProvider { protected AbstractResXResourceProvider() { } protected abstract ResourceManager ResourceManager { get; } public virtual object GetObject(string resourceKey, CultureInfo culture) { if (ResourceManager == null) { return null; } if (culture == null) { culture = CultureInfo.CurrentUICulture; } object item = ResourceManager.GetObject(resourceKey, culture); string strItem = item as string; if (strItem != null && culture.TwoLetterISOLanguageName != "fr" && culture != CultureInfo.InvariantCulture) { return string.Format(CultureInfo.InvariantCulture, "[{0}]{1}[/{0}]", culture.Name, strItem); } return item; } } }

构建全局资源提供者

全局资源提供者扩展了AbstractResXResourceProvider,并实现了对位于全局资源专用程序集中的资源管理器的访问。这个可以通过BuildManager的AppResourcesAssembly属性来检索。

解决方案使用了反射,因为没有在.NET API中找到任何现有的公共入口点来执行此操作。

protected virtual Assembly AppResourcesAssembly { get { Type buildManagerType = typeof(BuildManager); PropertyInfo property = buildManagerType.GetProperty("AppResourcesAssembly", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField); return (Assembly)property.GetValue(null, null); } }

构建本地资源提供者

实现的解决方案也使用了大量的反射,因为.NET API中缺乏执行此操作的入口点。

protected string VirtualPathFileName { get { PropertyInfo fileNameProperty = _virtualPathType.GetProperty("FileName"); return (string)fileNameProperty.GetValue(_virtualPathInstance, null); } } protected object VirtualPathParent { get { PropertyInfo parentProperty = _virtualPathType.GetProperty("Parent"); return parentProperty.GetValue(_virtualPathInstance, null); } } protected override ResourceManager ResourceManager { get { Assembly localResourceAssembly = LocalResourceAssembly; if (localResourceAssembly == null) { throw new InvalidOperationException("Unable to find the matching resource file."); } ResourceManager manager = new ResourceManager(VirtualPathFileName, localResourceAssembly); manager.IgnoreCase = true; return manager; } }

Web应用程序配置

像往常一样,在ASP.NET中,web.config文件允许修改用于全球化的ResourceProviderFactoryType。

<configuration> <system.web> <globalization resourceProviderFactoryType="MyProject.Resources.CulturePrefixedResourceProviderFactory" culture="fr-FR" uiCulture="fr-FR" /> </system.web> </configuration>

下一步是什么?

正如所看到的,为ASP.NET应用程序创建自定义资源提供者需要一些工作。在测试国际化应用程序时使用这个工具,以确保每个标签都在resx文件中正确填充。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485