2013-10-15 52 views
0

我需要使用appSettings定义的应用程序上下文检索本地资源:重写默认ResourceProvider

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

,并确定本地资源是这样的:这也可以与另一个值部署

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

<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> 

然后在asp中使用隐式资源名X页:

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

我试图实现一个自定义ResourceProvider所讲述的msdn但没有设法做一些有效的,也不简单。

任何想法如何在不重新实现整个ResourceProviderFactory的私密性?

编辑:

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

回答

1

据@BartoszKP意见,我写了一个定制ExpressionBuilder是考虑到acount的ApplicationContext和本地化(底座上的比拉尔·海达尔article):

网络。配置有权宣布它:

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

而且aspx页面就必须要求的ressource用一个前缀:

<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); 
    } 
} 
} 
-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> 
+0

我知道了如何获取的ApplicationContext – sinsedrix

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”,然后检查现有的资源。

+0

你在哪里考虑到ApplicationContext?你在哪里设置新的ResourceManager而不是默认的? – sinsedrix