2010-01-26 147 views
9

我有多個項目需要共享資源文件(.resx)已經提出了將資源文件移動到單獨的程序集並讓Web項目引用它的建議。有沒有一個如何做到這一點的例子?在Web應用程序之間共享asp.net資源文件

我是否創建一個新的類庫項目並將App_GlobalResource文件夾移動到那裏?我認爲這不會起作用,因爲爲資源文件生成的代碼類標記爲「內部」,這意味着它們不能在此程序集之外訪問。

回答

17

在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,你可以看看那裏的代碼示例。

+0

其良好的知道,我將無法訪問資源的aspx文件(其肯定在使用這樣的)。如果可以共享它,將很高興看到這個自定義ExpressionBuilder。 – 2010-01-26 16:23:53

+0

@ dev.e.loper:我已經更新了我的答案。 – Heinzi 2010-01-26 19:32:53

+1

@ Heinzi:該解決方案不會使獨立程序集通過文化解決資源問題。您將獲得默認文化的所有字符串,即使這些字符串爲當前文化定義了額外的resx。 – Sergio 2014-03-19 16:20:14

7

我們有一個已經開發的應用程序,我們必須擁有所有資源文件的兩個副本,一個用於服務,另一個用於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> 
+0

不錯。這工作! – Fanda 2016-12-08 12:58:44

相關問題