在Web应用程序之间共享asp.net资源文件

dev*_*per 11 asp.net resources resx

我有多个需要共享资源文件的项目(.resx)已经建议将资源文件移动到单独的程序集并让Web项目引用它.有一个如何做到这一点的例子?

我是否创建了一个新的类库项目并在其中移动App_GlobalResource文件夹?我认为这不会起作用,因为为资源文件生成的代码类被标记为"内部",这意味着它们无法在此程序集之外访问.

Hei*_*nzi 21

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

什么不会在这一点上的工作是利用资源的表达,例如,<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
Run Code Online (Sandbox Code Playgroud)

然后我们需要在web.config中注册这个ExpressionBuilder:

<system.web>
  ...
  <compilation ...>
    <expressionBuilders>
      <add expressionPrefix="Code" type="NamespaceOfYourLibrary.CodeExpressionBuilder" />
    </expressionBuilders>
  </compilation>
</system.web>
Run Code Online (Sandbox Code Playgroud)

现在您应该能够执行以下操作:

<asp:Button runat="server" Text="<%$ Code:[Namespace.]Resources.NameOfResx.MyButtonText %>" />
Run Code Online (Sandbox Code Playgroud)

Credit:我从Infinites Loop博客获得了CodeExpressionBuilder的想法.如果你比VB更喜欢C#,你可以看看那里的代码示例.


Pet*_*ter 8

我们有一个已经开发的应用程序,我们必须拥有所有资源文件的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

替换OneTypeInResourceAssembly为包含资源的程序集中的类型.

之后你可以将以下内容添加到web.config中,它应该正常工作..

<system.web>
  <compilation>
    <expressionBuilders>
      <remove expressionPrefix="Resources" />
      <add expressionPrefix="Resources" type="Assembly.ResourceExpressionBuilder" />
    </expressionBuilders>
  </compilation>
</system.web>
Run Code Online (Sandbox Code Playgroud)