我有多個項目需要共享資源文件(.resx)已經提出了將資源文件移動到單獨的程序集並讓Web項目引用它的建議。有沒有一個如何做到這一點的例子?在Web應用程序之間共享asp.net資源文件
我是否創建一個新的類庫項目並將App_GlobalResource文件夾移動到那裏?我認爲這不會起作用,因爲爲資源文件生成的代碼類標記爲「內部」,這意味着它們不能在此程序集之外訪問。
我有多個項目需要共享資源文件(.resx)已經提出了將資源文件移動到單獨的程序集並讓Web項目引用它的建議。有沒有一個如何做到這一點的例子?在Web應用程序之間共享asp.net資源文件
我是否創建一個新的類庫項目並將App_GlobalResource文件夾移動到那裏?我認爲這不會起作用,因爲爲資源文件生成的代碼類標記爲「內部」,這意味着它們不能在此程序集之外訪問。
在Visual Studio的屬性窗口中,您應該能夠將資源文件的訪問修飾符設置爲public。但是,您不能使用正常的<%$ Resources:... %>
語法訪問aspx文件中的資源,因爲它不支持引用程序集中的資源。我遇到了同樣的問題,並通過實現一個自定義的ExpressionBuilder解決了這個問題,但目前我還沒有訪問我的源代碼。如果仍然需要,那麼我可以在今晚查看代碼。
編輯:好的,這是我如何解決了這個問題:
步驟1:將RESX文件到類庫。他們不需要在特定的文件夾中。在RESX文件的可視化設計,設置「訪問修飾符」(上右上角),「公開」,
您現在應該能夠
參考資源C#/。 VB代碼(庫以及在Web項目),例如,Dim myMessage As String = [Namespace.]Resources.NameOfResx.NameOfResource
參考資源在aspx頁面嵌入代碼,例如,<h1><%= [Namespace.]Resources.NameOfResx.MyTitle %></h1>
。
什麼將在這一點上沒有工作是利用資源的表達,例如,<asp:Button runat="server" Text="<%$ Resources:NameOfResx,MyButtonText %>" />
。不幸的是,你不能簡單地用內聯代碼替換它,因爲它在服務器端控件的屬性中。
第2步:讓我們在我們的庫中製作一個定製的ExpressionBuilder,它解釋任意代碼表達式。幸運的是,我們可以讓.NET Framework的強大的階級做所有的工作我們:
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
然後,我們需要註冊的ExpressionBuilder在web.config:
<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 blog上心的CodeExpressionBuilder。如果你更喜歡C#而不是VB,你可以看看那裏的代碼示例。
我們有一個已經開發的應用程序,我們必須擁有所有資源文件的兩個副本,一個用於服務,另一個用於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>
不錯。這工作! – Fanda 2016-12-08 12:58:44
其良好的知道,我將無法訪問資源的aspx文件(其肯定在使用這樣的)。如果可以共享它,將很高興看到這個自定義ExpressionBuilder。 – 2010-01-26 16:23:53
@ dev.e.loper:我已經更新了我的答案。 – Heinzi 2010-01-26 19:32:53
@ Heinzi:該解決方案不會使獨立程序集通過文化解決資源問題。您將獲得默認文化的所有字符串,即使這些字符串爲當前文化定義了額外的resx。 – Sergio 2014-03-19 16:20:14