2010-03-29 59 views
5

Tôi muốn ghi đè một chuỗi từ một System.ComponentModel.DataAnnotations cho một dự án ASP.NET. Tôi có cần phải lắp ráp vệ tinh, làm rối tung các nhiệm vụ xây dựng tùy chỉnh, al.exe, v.v. không? Ngay cả khi có, tôi không thể tìm cách chuyển đổi .resx thành .resources để cấp dữ liệu cho al.exe. Và nếu không, nơi đặt .resx. và cách đặt tên?Ghi đè tài nguyên từ assembly chuẩn trong ASP.NET

UPD: Để làm cho nó rõ ràng: Tôi muốn sử dụng một chuỗi tài nguyên tùy chỉnh thay vì một từ nguồn tài nguyên mặc định từ lắp ráp. Tôi không muốn thay đổi ở mọi nơi sử dụng chuỗi đó. Sau khi tất cả, các nguồn lực tồn tại chỉ để ghi đè chúng.

Trả lời

2

Trong khi điều này là lạ, đặc biệt là cho những người quen thuộc với công nghệ nội địa hóa nguồn mở, người ta không thể xây dựng một lắp ráp vệ tinh cho bất kỳ lắp ráp hệ thống hoặc thậm chí là một bên thứ 3 đã ký một:

If your main assembly uses strong naming, satellite assemblies must be signed with the same private key as the main assembly. If the public/private key pair does not match between the main and satellite assemblies, your resources will not be loaded.

Cho dù điều tương tự có thể tự động, nhưng không có lắp ráp vệ tinh, là không rõ, mặc dù tôi nghi ngờ điều đó.

1

Giả sử bạn muốn ghi đè lên các dây thông báo lỗi mặc định trong các thuộc tính xác nhận, bạn có thể làm điều đó bằng cách thiết lập ErrorMessageResourceNameErrorMessageResourceType tính như thế này:

[Required(ErrorMessageResourceName = "Required_Username", ErrorMessageResourceType = typeof(MyResourceFile)] 
public string Username { get; set; } 

Bạn có thể tạo một tập tin tài nguyên được gọi là MyResourceFile .resx chứa Required_Username cùng với thông báo lỗi bạn muốn.

Hy vọng điều này sẽ hữu ích.

+0

Tôi biết điều này, nhưng tôi không muốn thay đổi tất cả các thuộc tính. – wRAR

4

Phil Haack có một bài viết xuất sắc Localizing ASP.Net MVC Validation hướng dẫn cụ thể bạn thông qua việc ghi đè các chuỗi của bạn. Bài viết này áp dụng nhiều hơn cho DataAnnotations so với số ASP.net MVC. Do đó, điều này sẽ giúp bạn sử dụng DataAnnotattions.

Dưới đây tôi đã liệt kê các bước đơn giản nhất để thêm Tài nguyên được bản địa hóa trong Visual Studio.

  1. Mở hộp thoại Project Properties.
  2. Chọn tab Resources.
  3. Nhấp để tạo mới mặc định tài nguyên tệp.
  4. Thao tác này sẽ tạo hai tệp trong thư mục Properties của bạn.
    • Resources.resx
    • Resources.Designer.cs
  5. Khi Resources.resx đã mở, thay đổi nó Access Modifier để Public.
  6. Thêm chuỗi của bạn.

Để bổ sung thêm tập tin tài nguyên cho nền văn hóa cụ thể bạn sẽ cần phải.

  1. Nhấp chuột phải Project trong Solution Explorer của bạn.
  2. Chọn Thêm -> New Item ->Resource File.
  3. Đặt tên là Resources.en-us.resx. (thay thế 'en-us' với mã thích hợp)
  4. Nhấn Add
  5. Kéo nó vào thư mục Properties.
  6. mở Resources.en-us.resx và thay đổi nó Access Modifier để Public.
  7. Thêm chuỗi của bạn.
  8. Lặp lại cho mỗi nền văn hóa bạn cần hỗ trợ.

Trong xây dựng VS sẽ chuyển đổi các Resx file .resource tập tin và xây dựng các lớp wrapper cho bạn. Sau đó, bạn có thể truy cập qua không gian tên YourAssembly.Properties.Resources.

Với tuyên bố sử dụng này.

using YourAssembly.Properties; 

Bạn có thể trang trí với các thuộc tính như thế này:

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "MyStringName")] 

Lưu ý: Tôi sử dụng Thuộc tính thư mục cho nhất quán. Để sử dụng App_GlobalResources, hãy di chuyển các tệp .resx vào đó và thay đổi câu lệnh sử dụng của bạn để khớp với tên thư mục. Như thế này:

using YourAssembly.App_GlobalResources; 

Edit: Gần nhất mà bạn có thể nhận để mạnh mẽ gõ tên tài nguyên sẽ làm điều gì đó như thế này:

public class ResourceNames 
{ 
    public const string EmailRequired = "EmailRequired"; 
} 

Sau đó bạn có thể trang trí với các thuộc tính như thế này.

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = ResourceNames.EmailRequired)] 

Để kích hoạt tự động phát hiện văn hóa client thêm globalizationsection đến web.config tập tin.

<configuration> 
    <system.web> 
     <globalization enableClientBasedCulture="true" culture="auto:en-us" uiCulture="auto:en-us"/> 
    </system.web> 
<configuration> 

Ở đây tôi đã kích hoạt một nền văn hóa dựa trên khách hàng và thiết lập văn hóauiculture để "auto" với một mặc định của "en-us".


Tạo Assemblies vệ tinh riêng:

MSDN Creating Satellite Assemblies bài viết sẽ giúp là tốt. Nếu bạn chưa quen với cụm vệ tinh, hãy đảm bảo bạn đọc Packaging and Deploying Resources.

Khi tạo các cụm vệ tinh trong quá khứ, tôi thấy hữu ích khi sử dụng các sự kiện VS build. Đây là những bước tôi sẽ thực hiện.

  1. Tạo dự án riêng biệt Class Library trong giải pháp của tôi.
  2. Tạo hoặc Thêm .resx tệp của dự án này.
  3. Thêm Post-Build Event vào hộp thoại Project Properties. (Giống như hình dưới đây)

Mẫu VS Post-Build Script:

set RESGEN="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\resgen.exe" 
set LINKER="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\al.exe" 
set ASSEMBLY=$(TargetName) 
set SOURCEDIR=$(ProjectDir) 
Set OUTDIR=$(TargetDir) 

REM Build Default Culture Resources (en) 
%RESGEN% %SOURCEDIR%en\%ASSEMBLY%.en.resx %SOURCEDIR%en\%ASSEMBLY%.resources 

REM Embed Default Culture 
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%%ASSEMBLY%.resources.dll 
REM Embed English Culture 
IF NOT EXIST %OUTDIR%en\ MKDIR $%OUTDIR%en\ 
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%en\%ASSEMBLY%.resources.dll 


REM These are just a byproduct of using the project build event to run the resource build script 
IF EXIST %OUTDIR%%ASSEMBLY%.dll DEL %OUTDIR%%ASSEMBLY%.dll 
IF EXIST %OUTDIR%%ASSEMBLY%.pdb DEL %OUTDIR%%ASSEMBLY%.pdb 

Nếu bạn không muốn sử dụng ResGen.exe để chuyển đổi .resx các tập tin, bạn có thể làm một cái gì đó như thế này .

using System; 
using System.Collections; 
using System.IO; 
using System.Resources; 

namespace ResXConverter 
{ 
    public class ResxToResource 
    { 
     public void Convert(string resxPath, string resourcePath) 
     { 
      using (ResXResourceReader resxReader = new ResXResourceReader(resxPath)) 
      using (IResourceWriter resWriter = new ResourceWriter(
        new FileStream(resourcePath, FileMode.Create, FileAccess.Write))) 
      { 
       foreach (DictionaryEntry entry in resxReader) 
       { 
        resWriter.AddResource(entry.Key.ToString(), entry.Value); 
       } 
       resWriter.Generate(); 
       resWriter.Close(); 
      } 
     } 
    } 
} 

Một trong những lợi thế rút lại tiềm năng khi thực hiện chuyển đổi theo cách này là cần tham khảo System.Windows.Forms.dll. Bạn sẽ vẫn cần sử dụng Assembly Linker.

Chỉnh sửa: Vì wRAR đã nhắc nhở chúng tôi nếu bạn đang ký hợp đồng với các phím của mình must match.

+0

Tôi đã đọc tất cả các liên kết này. Liên kết đầu tiên đề xuất đặt tên tài nguyên trong các thuộc tính một cách rõ ràng, đây không phải là những gì tôi muốn. Đối với các hội đồng vệ tinh, tôi vẫn không thể hiểu (và thậm chí tìm thấy vị trí thích hợp trong MSDN) cách lắp ráp, vùng tên và tài nguyên được đặt tên để được tải bởi thời gian chạy và liệu các yêu cầu bổ sung có tồn tại hay không. System.ComponentModel.DataAnnotations.resources.dll chứa System.ComponentModel.DataAnnotations.resources hoặc System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resources dường như không được tải. – wRAR

+0

@wRAR: Trước khi chúng tôi đặt tên cho các quy ước, bạn có muốn chỉ định thời gian chạy loại thông báo nào được hiển thị hay không mà bạn không muốn chuỗi trong thuộc tính của mình? – VoidDweller

+0

Tôi chỉ muốn bản địa hóa các chuỗi chuẩn. – wRAR

0

Nếu máy chủ không có gói ngôn ngữ .NET được cài đặt, bất kể CurrentUICulture được đặt là gì, bạn sẽ luôn nhận được tiếng Anh trong thông báo xác thực DataAnnotations. Hack sử thi này hoạt động cho chúng tôi.

  • Đến "Microsoft .NET Framework 4.6.1 Language Pack" tải trang https://www.microsoft.com/en-us/download/details.aspx?id=49977
  • Chọn ngôn ngữ và tải
  • Extract NDP461-KB3102436-x86-x64-AllOS- {} LANG Exe với 7 -Zip
  • Extract file CAB x64-Windows10.0-KB3102502-x64.cab với 7-Zip
  • Xác định vị trí "msil_system.componentmod..notations.resources _...."
  • ... trong đó bạn sẽ tìm thấy "system.componentmodel.dataannotations.resources.dll"
  • Mở .resources.dll với ILSpy, tìm Tài nguyên và nhấp vào nút Lưu bên trên Bảng Chuỗi để lưu dưới dạng System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources. {LANGUAGE} .resources
  • Thêm vào dự án của bạn dưới dạng "Tài nguyên "
  • Đảm bảo các tập tin Xây dựng tài sản hành động của các tập tin nguồn được thiết lập để 'Embedded Resource'

Sau đó, trong một phương pháp PreStart của dự án của bạn, bạn ghi đè lên System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resourceMan lĩnh vực tĩnh tư nhân (đã nói với bạn đó là một hack) với những cái bạn có trong dự án của bạn.

using System; 
using System.Linq; 
using System.Reflection; 
using System.Resources; 

[assembly: WebActivator.PreApplicationStartMethod(typeof(ResourceManagerUtil), nameof(ResourceManagerUtil.PreStart))] 

class ResourceManagerUtil 
{ 
    public static void PreStart() 
    { 
     initDataAnnotationsResourceManager(); 
    } 

    /// <summary> 
    /// If the server doesn't have .NET language packs installed then no matter what CurrentUICulture is set to, you'll always get English in 
    /// DataAnnotations validation messages. Here we override DataAnnotationsResources to use a ResourceManager that uses language .resources 
    /// files embedded in this assembly. 
    /// </summary> 
    static void initDataAnnotationsResourceManager() 
    { 
     var embeddedResourceNamespace = "<YourProjectDefaultNamespace>.<FolderYouSavedResourcesFilesIn>"; 
     var dataAnnotationsResourcesName = "System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources"; 
     var thisAssembly = typeof(ResourceManagerUtil).Assembly; 
     var dataAnnotationsAssembly = typeof(System.ComponentModel.DataAnnotations.ValidationAttribute).Assembly; 

     var resourceManager = new ResourceManager(embeddedResourceNamespace + "." + dataAnnotationsResourcesName, thisAssembly); 

     // Set internal field `DataAnnotationsResources.resourceMan` 
     var dataAnnotationsResourcesType = dataAnnotationsAssembly.GetType(dataAnnotationsResourcesName); 
     var resmanProp = dataAnnotationsResourcesType.GetField("resourceMan", BindingFlags.NonPublic | BindingFlags.Static); 
     resmanProp.SetValue(null, resourceManager); 
    } 
} 
Các vấn đề liên quan