0

我需要使用以下定义的应用程序上下文检索本地资源appSettings

<add key="ApplicationContext" value="CTX1"/>

也可以使用另一个值进行部署:

<add key="ApplicationContext" value="CTX2"/>

并像这样定义本地资源:

<root>
  <data name="CTX1_BodyTitle1" xml:space="preserve">
    <value>Welcome to context 1</value>
  </data> 

  <data name="CTX2_BodyTitle1" xml:space="preserve">
    <value>Welcome to context 2</value>
  </data> 
<root>

然后在 aspx 页面中使用隐式资源名称:

<h2><asp:Literal runat="server" meta:ressourcekey="BodyTitle1"></asp:Literal></h2>

我尝试按照msdn上的说明实现自定义 ResourceProvider,但没有设法做一些有效或简单的事情。

知道如何在不重新实现整体的情况下实现这一点ResourceProviderFactory吗?

编辑:

我想根据 ApplicationContext隐式检索本地资源Page1.en.resx,然后使用唯一标识符链接到定义的资源。Page1.fr.resxPage1.aspx

4

3 回答 3

1

根据@BartoszKP 的建议,我编写了一个自定义ExpressionBuilder应用程序上下文和本地化(基于 Bilal Haidar文章):

Web.config 必须声明它:

<system.web>
    <expressionBuilders>
        <add expressionPrefix="Contextual" type="SinsedrixLibrary.ContextualExpressionBuilder"/>
    </expressionBuilders>
</system.web>

而 aspx 页面只需要请求带有前缀的资源:

<h1><asp:Literal runat="server" Text='<%$ Contextual: LitWelcome %>'></asp:Literal></h1>

这是ExpressionBuilder

namespace SinsedrixLibrary
{
/// <summary>
/// This source file includes the source code for the 
/// XmlSettingExpressionBuilder, which is used to handle
/// declarative expressions based on an XML settings file.
/// </summary>
public class ContextualExpressionBuilder : ExpressionBuilder
{
    public ContextualExpressionBuilder()
    { }
    /// <summary>
    /// This method will be called during page execution
    /// to get the expression that is going to be executed 
    /// to return the value of the declarative expression
    /// </summary>
    /// <param name="entry"></param>
    /// <param name="parsedData"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
    {
        // Get a reference to this class since we are going to
        // execute a method on this class that will evaluate
        // the required expression
        CodeTypeReferenceExpression thisType = new CodeTypeReferenceExpression(base.GetType());

        // Create a new expression based on the KEY specified
        // in the declarative expression, this will be used
        // as an input to the method that will evaluate the 
        // required expression
        CodePrimitiveExpression expression = new CodePrimitiveExpression(entry.Expression.Trim().ToString());
        string l_resxPath = Path.GetDirectoryName(context.VirtualPath) + "\\App_LocalResources\\"+ Path.GetFileName(context.VirtualPath);
        CodePrimitiveExpression resxPath = new CodePrimitiveExpression(l_resxPath);

        // The static method name that will evaluate the
        // expression, by accessing the XML file and retreiving
        // the value that corresponds to the key specified
        string evaluationMethod = "GetContextResource";

        // Finally, return the expression that will invoke the method
        // responsible for evaluating the expression
        // The CodeMethodInvokeExpression takes as input the type on which to execute the method specified,
        // the method name, and the array of CodeExpression, which represents the parameters of the method called
        return new CodeMethodInvokeExpression(thisType, evaluationMethod, new CodeExpression[] { expression, resxPath });
    }

    /// <summary>
    /// Evaluates the expression by accessing the XMLSettings file
    /// and retrieve the value corresponding to the key specified in
    /// the input expression.
    /// </summary>
    /// <param name="expression"></param>
    /// <returns></returns>
    public static string GetContextResource(string expression, string resxPath)
    {
        // Get the XML Setting file from the application cache if present
        CultureInfo ci = CultureInfo.CurrentCulture;
        string resxKey = resxPath + "." + ci.TwoLetterISOLanguageName;

        XmlDocument xmlSettingDoc = (XmlDocument)HostingEnvironment.Cache[resxKey];

        // check if there was an already loaded document
        if (xmlSettingDoc == null)
        {
            // Define the document here
            xmlSettingDoc = new XmlDocument();

            // Get the config file path using the HostingEnvironment
            // which gives information for application-specific
            string resxCultureFile = resxKey + ".resx";
            string resxDefaultFile = resxPath + ".resx";
            string resxFile = "";
            try
            {
                resxFile = HostingEnvironment.MapPath(resxCultureFile);
            }
            catch(Exception) {
                resxFile = HostingEnvironment.MapPath(resxDefaultFile);
            }

            // Load the XML file into the XmlDocument
            xmlSettingDoc.Load(resxFile);

            // Create a new file dependency to be used when we add the XmlDocument
            // into the Cache, so that when the XmlSettings file change, the Cache will
            // be invalid.
            CacheDependency settingsDepend = new CacheDependency(resxFile);

            // Add the Xmldocument to the Cache
            HostingEnvironment.Cache.Insert(resxKey, xmlSettingDoc, settingsDepend);
        }

        string ctx = ConfigurationManager.AppSettings["ApplicativeContext"];

        // XPATH key used to retrieve the record needed in the form of add[@key='keyvalue']
        string getXPATHKey = String.Format("//data[@name='{0}_{1}']/value", ctx, expression);

        // Search for that record
        XmlNode wantedRecord = xmlSettingDoc.SelectSingleNode(getXPATHKey);

        // If the record exists, return the value property
        if (wantedRecord != null)
            return wantedRecord.InnerText;

        // return a message informing users that the expression failed to
        // evaluate to a real value
        return string.Format("Unable to Process Expression : '{0}'", expression);
    }
}
}
于 2013-10-29T09:53:15.353 回答
0

在我的团队开发的一个应用程序中,我们首先创建一个 OverridenResourceManager 来处理这个问题,它继承了下面提供的 ResourceManager (System.Resources) 示例代码:

    /// <summary>
/// Resource manager that uses resources found in the exceptions folder before falling back to the built-in resource file.
/// </summary>
public class OverridenResourceManager : ResourceManager
{

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="OverridenResourceManager "/>lass.
    /// </summary>
    /// <param name="name">
    /// The name of the resource file.
    /// </param>
    /// <param name="culture">
    /// The string culture to find resources for.
    /// </param>
    public OverridenResourceManager(string name, Assembly culture)
        : base(name, culture)
    {
        this.Name = name.Replace("AssemblyName.Localization.", string.Empty);
    }

    #endregion

    #region Public Properties

    /// <summary>
    /// Gets or sets a function that return a dictionary of overrides for the currentsite
    /// </summary>
    public static Func<Dictionary<string, string>> TextOverridesDictionary { get; set;}

    /// <summary>
    /// Gets or sets the name of the resources class to handle.
    /// </summary>
    public string Name { get; set; }

    #endregion

    #region Public Methods and Operators

    /// <summary>
    /// Gets the resource named <paramref name="name"/> for the given <paramref name="culture"/>.
    /// Tries to use the value in an exceptions file (through a pre-built dictionary), if any,
    /// otherwise uses the built-in method.
    /// </summary>
    /// <param name="name">
    /// The name of the resource to get.
    /// </param>
    /// <param name="culture">
    /// The string culture to get the resource for.
    /// </param>
    /// <returns>
    /// The <see cref="string"/> containing the value of the resource.
    /// </returns>
    public override string GetString(string name, CultureInfo culture)
    {
        if (TextOverridesDictionary != null)
        {
            // As we are only giving one file we need to fully qualify the name we are looking for
            var resourceName = this.Name + '.' + name;

            // TextOverridesDictionary contains a closure to get the dictionary
            // from the session's website configuration object
            var overrides = TextOverridesDictionary();
            if (overrides != null && overrides.ContainsKey(resourceName))
            {
                return overrides[resourceName];
            }
        }

        return base.GetString(name, culture);
    }
}

当应用程序启动时,我们然后设置

TextOverridesDictionary = () => Session.Site.TextResourceOverrides;

简而言之,它调用了一个方法来获取所提供资源的字典键/值对。您需要实现一种从 .config 文件中获取正确键/值的方法,该方法非常简单。如果需要,我可以提供示例代码。

使用此 OverridenResourceManager,同一命名空间中的任何资源,对于我们来说,“AssemblyName.Localization”,将首先根据我们的字典检查,然后是现有资源。

于 2013-10-28T23:24:11.720 回答
-1

就我而言,有一种简单的方法可以做到这一点,但让我分享一下我认为可以帮助你的方法

创建一个类,您可以在其中访问 webconfing 或 appconfig 文件,如下所示

public static class appdata
{

    static ResourceManager rm = new ResourceManager("Resources.Resource", System.Reflection.Assembly.Load("App_GlobalResources"));
 static     CultureInfo ci =  default(CultureInfo);


    private static isValidChassisTableAdapter _isvalidchassis = null;
    private static SG_FORMTableAdapter _sgform = null;
    private static settingTableAdapter _setting = null;
    private static IsInRoleTableAdapter _Role = null;
    private static tblaccountsTableAdapter _accounts = null;
    private static tblloginhistoryTableAdapter _AppEvents = null;

    private static configTableAdapter _AppConfig = null;
    public static configTableAdapter AppConfig
    {
        get
        {
            if (_AppConfig == null)
            {
                _AppConfig = new configTableAdapter();
            }

            return _AppConfig;
        }
    }
public static string ApplicationContext
    {
        get { return ConfigurationManager.AppSettings.Get("ApplicationContext"); }
    }
}

然后像这样在aspx页面中使用它

<h2><%=appdata.ApplicationContext%></h2>
于 2013-10-26T20:01:32.937 回答