在 Web 應用程序之間共享 asp.net 資源文件
我有多個項目需要共享資源文件 (.resx) 已建議將資源文件移動到單獨的程序集並讓 Web 項目引用它。有如何做到這一點的例子嗎?
我是否創建一個新的類庫項目並在其中移動 App_GlobalResource 文件夾?我認為這不會起作用,因為為資源文件生成的程式碼類被標記為“內部”,這意味著它們無法在此程序集之外訪問。
在 Visual Studio 的屬性視窗中,您應該可以將資源文件的訪問修飾符設置為 public。但是,您將無法使用正常
<%$ Resources:... %>語法訪問 aspx 文件中的資源,因為它不支持引用程序集中的資源。我遇到了同樣的問題,並通過實現自定義 ExpressionBuilder 解決了它,但我目前無法訪問我的原始碼。如果還需要的話,我今晚可以查一下程式碼。編輯:好的,這就是我解決這個問題的方法:
第 1 步:將 resx 文件移動到類庫中。它們不需要位於特定文件夾中。在 resx 文件的視覺化設計器中,將“Access Modifier”(右上角)設置為“Public”
您現在應該能夠
- 引用C#/VB 程式碼中的資源(在庫中以及在 Web 項目中),例如,
Dim myMessage As String = [Namespace.]Resources.NameOfResx.NameOfResource- 在 aspx 頁面中將資源作為內聯程式碼引用,例如
<h1><%= [Namespace.]Resources.NameOfResx.MyTitle %></h1>.此時不起作用的是使用 Resources 表達式,例如
<asp:Button runat="server" Text="<%$ Resources:NameOfResx,MyButtonText %>" />. 不幸的是,您不能簡單地將其替換為內聯程式碼,因為它位於伺服器端控制項的屬性中。第 2 步:讓我們在我們的庫中創建一個自定義的 ExpressionBuilder,它可以解釋任意程式碼表達式。幸運的是,我們可以讓 .net 框架的強大類為我們完成所有工作:
Imports System.Web.Compilation Imports System.Resources Imports System.CodeDom <ExpressionPrefix("Code")> _ Public Class CodeExpressionBuilder Inherits ExpressionBuilder Public Overrides Function GetCodeExpression(ByVal entry As System.Web.UI.BoundPropertyEntry, ByVal parsedData As Object, ByVal context As System.Web.Compilation.ExpressionBuilderContext) As System.CodeDom.CodeExpression Return New CodeSnippetExpression(entry.Expression) End Function End Class然後我們需要在 web.config 中註冊這個 ExpressionBuilder:
<system.web> ... <compilation ...> <expressionBuilders> <add expressionPrefix="Code" type="NamespaceOfYourLibrary.CodeExpressionBuilder" /> </expressionBuilders> </compilation> </system.web>現在您應該能夠執行以下操作:
<asp:Button runat="server" Text="<%$ Code:[Namespace.]Resources.NameOfResx.MyButtonText %>" />信用:我從Infinites Loop 部落格中得到了 CodeExpressionBuilder 的想法。如果您更喜歡 C# 而不是 VB,則可以查看那裡的程式碼範例。
我們已經開發了一個應用程序,其中我們必須擁有所有資源文件的 2 個副本,一份用於服務,一份用於 asp.net 項目,而且該項目依賴於
<%$ Resources:NameOfResx,MyButtonText %>語法,因此無法更改語法。一段時間後,我找到了 ExpressionBuilder 並提出了以下解決方案:
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Web.Compilation; using System.Resources; using System.CodeDom; using System.Reflection; /// <summary> /// This class allows asp.net Resource lookups to different assembly /// </summary> [ExpressionPrefix("Resources")] public class ResourceExpressionBuilder : ExpressionBuilder { static readonly Dictionary<string, ResourceManager> mResourceManagers = new Dictionary<string, ResourceManager>(StringComparer.OrdinalIgnoreCase); static ResourceExpressionBuilder() { Assembly resourceAssembly = Assembly.GetAssembly(typeof(OneTypeInResourceAssembly)); const string suffix = ".resources"; string assemblyName = resourceAssembly.GetName().Name; foreach (string resource in resourceAssembly.GetManifestResourceNames()) { if ((resource.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))) { string resourceName = resource.Substring(0, resource.Length - suffix.Length); string resourceFriendlyName = resourceName.Substring(assemblyName.Length + 1, resourceName.Length - (assemblyName.Length + 1)); mResourceManagers.Add(resourceFriendlyName, new ResourceManager(resourceName, resourceAssembly)); } } } /// <summary> /// When overridden in a derived class, returns a value indicating whether the current <see cref="T:System.Web.Compilation.ExpressionBuilder" /> object supports no-compile pages. /// </summary> /// <returns>true if the <see cref="T:System.Web.Compilation.ExpressionBuilder" /> supports expression evaluation; otherwise, false.</returns> public override bool SupportsEvaluate { get { return true; } } /// <summary> /// When overridden in a derived class, returns an object that represents an evaluated expression. /// </summary> /// <param name="target">The object containing the expression.</param> /// <param name="entry">The object that represents information about the property bound to by the expression.</param> /// <param name="parsedData">The object containing parsed data as returned by <see cref="M:System.Web.Compilation.ExpressionBuilder.ParseExpression(System.String,System.Type,System.Web.Compilation.ExpressionBuilderContext)" />.</param> /// <param name="context">Contextual information for the evaluation of the expression.</param> /// <returns> /// An object that represents the evaluated expression; otherwise, null if the inheritor does not implement <see cref="M:System.Web.Compilation.ExpressionBuilder.EvaluateExpression(System.Object,System.Web.UI.BoundPropertyEntry,System.Object,System.Web.Compilation.ExpressionBuilderContext)" />. /// </returns> public override object EvaluateExpression(object target, System.Web.UI.BoundPropertyEntry entry, object parsedData, System.Web.Compilation.ExpressionBuilderContext context) { if ((parsedData != null && object.ReferenceEquals(parsedData.GetType(), typeof(string)))) { return GetRequestedValue(Convert.ToString(parsedData)); } return base.EvaluateExpression(target, entry, parsedData, context); } /// <summary> /// When overridden in a derived class, returns code that is used during page execution to obtain the evaluated expression. /// </summary> /// <param name="entry">The object that represents information about the property bound to by the expression.</param> /// <param name="parsedData">The object containing parsed data as returned by <see cref="M:System.Web.Compilation.ExpressionBuilder.ParseExpression(System.String,System.Type,System.Web.Compilation.ExpressionBuilderContext)" />.</param> /// <param name="context">Contextual information for the evaluation of the expression.</param> /// <returns> /// A <see cref="T:System.CodeDom.CodeExpression" /> that is used for property assignment. /// </returns> public override System.CodeDom.CodeExpression GetCodeExpression(System.Web.UI.BoundPropertyEntry entry, object parsedData, System.Web.Compilation.ExpressionBuilderContext context) { CodeExpression[] inputParams = new CodeExpression[] { new CodePrimitiveExpression(entry.Expression.Trim()) }; return new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.GetType()), "GetRequestedValue", inputParams); } /// <summary> /// Gets the requested value. /// </summary> /// <param name="expression">The expression.</param> /// <returns></returns> public static object GetRequestedValue(string expression) { string[] parts = expression.Split(new char[] { ',' }, 2, StringSplitOptions.None); if ((parts.Length != 2)) { throw new ArgumentException("Expression must contain ,"); } string resourceFile = parts[0].Trim(); string resourceName = parts[1].Trim(); return mResourceManagers[resourceFile].GetString(resourceName); } }替換
OneTypeInResourceAssembly為包含資源的程序集中的類型。之後,您可以將以下內容添加到 web.config 中,它應該可以正常工作..
<system.web> <compilation> <expressionBuilders> <remove expressionPrefix="Resources" /> <add expressionPrefix="Resources" type="Assembly.ResourceExpressionBuilder" /> </expressionBuilders> </compilation> </system.web>