如何將C#資源文件字符串轉換為方法而不僅僅是屬性?

asp.net-core asp.net-core-localization c# entity-framework-core resx

例如,EntityFramework Microsoft.EntityFrameworkCore.Relational項目在資源文件中包含以下文本:

...
<data name="FromSqlMissingColumn" xml:space="preserve">
  <value>The required column '{column}' was not present in the results of a 'FromSql' operation.</value>
</data>
...

它生成以下C#代碼:

...
/// <summary>
/// The required column '{column}' was not present in the results of a 'FromSql' operation.
/// </summary>
public static string FromSqlMissingColumn([CanBeNull] object column)
{
    return string.Format(CultureInfo.CurrentCulture, GetString("FromSqlMissingColumn", "column"), column);
}
...
private static string GetString(string name, params string[] formatterNames)
{
    var value = _resourceManager.GetString(name);

    Debug.Assert(value != null);

    if (formatterNames != null)
    {
        for (var i = 0; i < formatterNames.Length; i++)
        {
            value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
        }
    }

    return value;
}
...

但是當我在VS中編輯文件並保存它時,我只生成了簡單的屬性,如:

...
/// <summary>
/// The required column '{column}' was not present in the results of a 'FromSql' operation.
/// </summary>
public static string FromSqlMissingColumn
{
    get { return ResourceManager.GetString("FromSqlMissingColumn"); }
}
...

有問題的文件可以在這裡找到:

那麼問題又來了 - 他們是怎麼做到的,我怎麼能得到相同的結果呢?

一般承認的答案

他們是如何做到的呢?

首先,顯而易見的是,他們不使用標準的ResXFileCodeGenerator ,而是使用一些自定義代碼生成工具。

目前有兩種生成代碼的標準方法 - 使用類似於ResXFileCodeGeneratorCustom Tool的舊學校方式,或使用T4模板的現代方式。所以讓我們看看。

Microsoft.EntityFrameworkCore.Relational.csproj文件中的對應條目如下所示:

<ItemGroup> 
    <EmbeddedResource Include="Properties\RelationalStrings.resx">
        <LogicalName>Microsoft.EntityFrameworkCore.Relational.Properties.RelationalStrings.resources</LogicalName> 
    </EmbeddedResource> 
</ItemGroup> 

我們可以看到,他們肯定不使用Custom Tool

所以它應該是一個T4模板。確實在上面的項目之後我們可以看到:

<ItemGroup> 
    <Content Include="..\..\tools\Resources.tt"> 
        <Link>Properties\Resources.tt</Link> 
            <Generator>TextTemplatingFileGenerator</Generator> 
            <LastGenOutput>Resources.cs</LastGenOutput> 
            <CustomToolNamespace>Microsoft.EntityFrameworkCore.Internal</CustomToolNamespace> 
    </Content> 
    <Content Include="Properties\Microsoft.EntityFrameworkCore.Relational.rd.xml" /> 
</ItemGroup> 

你去吧!

現在,我不知道所包含的xml文件的目的是什麼,而不是潛入實現(它可能是生成器使用的東西,如選項或其他東西),但實際的代碼生成包含在以下資源中。 tt文件。

我怎麼能得到相同的結果?

我想你要求自己的項目。好吧,你可以做類似的事情。選擇您的resx文件,轉到“ Properties並清除“ Custom Tool 。然後將T4 template添加到項目中並編寫代碼生成(我不確定許可證是否允許您使用他們的代碼,因此如果您想這樣做,請確保首先檢查是否允許它)。但原則是一樣的。


熱門答案

我認為,EF團隊為此目的使用自己的自Custom ToolCustom Tool 。但是visual studio使用PublicResXFileCodeGenerator作為.resx文件的默認自定義工具,這個工具沒有PublicResXFileCodeGenerator這樣的功能,它的基類ResXFileCodeGenerator (兩者都可以在Microsoft.VisualStudio.Design程序ResXFileCodeGenerator找到)只是圍繞StronglyTypedResourceBuilder visual studio的包裝器。 。

它們是實現IVsSingleFileGenerator (位於Microsoft.VisualStudio.Shell.Interop程序IVsSingleFileGenerator )。因此,您可以開始實施自己的Custom Tool 。啟動新的Class Library ,添加Microsoft.VisualStudio.Shell.14.0Microsoft.VisualStudio.Shell.Interop引用。創建新類並實現此接口。接口IVsSingleFileGenerator非常簡單。它只包含兩種方法:

  • DefaultExtension返回生成文件的擴展名(帶有前導句點)作為out string pbstrDefaultExtensionVSConstant.S_OK作為返回值(當然,如果一切正常)。

  • Generate哪個是接受的:

    • wszInputFilePath - 輸入文件路徑,可以為null,不要使用它。
    • bstrInputFileContents - 應該使用輸入文件內容。
    • wszDefaultNamespace -默認命名空間(也說不清現在為什麼ResXFileCodeGenerator與Visual Studio互操作性展示獲得命名空間而不是使用此參數)。
    • rgbOutputFileContents - 生成文件的字節數組。您必須在返回的字節數組中包含UNICODE或UTF-8簽名字節,因為這是一個原始流。必須使用.NET Framework調用Marshal.AllocCoTaskMem或等效的Win32系統調用CoTaskMemAlloc分配rgbOutputFileContents的內存。項目系統負責釋放這些內存。
    • pcbOutput - rgbOutputFileContent數組中的字節數。
    • pGenerateProgress - 對IVsGeneratorProgress接口的引用,生成器可通過該接口向項目系統報告其進度。

    如果一切正常,或者相應的錯誤代碼,則返回VSConstant.S_OK

還有關於實施的小指南 。但是這本指南並沒有說太多。最有用的是如何註冊自己的生成器。

您最好深入研究ResXFileCodeGenerator代碼 (或簡單地反編譯)以獲取實現示例,或者獲取一些提示,例如如何與visual studio互操作。但我認為沒有理由與你所提供的所有你需要的東西互動。 .resx文件的內容可以通過讀取ResXResourceReader.FromFileContents

其餘的都很簡單,因為你有資源名稱和值,只需要返回生成的文件的字節數組。我認為,解析資源值以獲得無效格式的編譯時錯誤(例如: {{param}}} )將是最大的困難。

當解析值並找到即將發布的方法的參數時,您可以生成代碼(再次作為示例,您可以參考ResXFileCodeGeneratorStronglyTypedResourceBuilder ,或者通過CodeDom或手動編寫源代碼文本,按照您自己的方式自行完成)。這也應該不難,因為您已經有一個在您發布的問題中需要生成的方法的示例。

編譯自己的生成器,註冊它,在.resx文件的Custom Tool屬性中設置它,你將獲得帶有方法而不是屬性的資源類。

你也可以和其他人在github上分享它。 :)


這是來自自定義工具註冊的指令(因為msdn鏈接可能很快就會死掉):

要在Visual Studio中創建自定義工具,必須註冊它,以便Visual Studio可以實例化它並將其與特定項目類型相關聯。

  1. HKEY_CLASSES_ROOT下的Visual Studio本地註冊表或系統註冊表中註冊自定義工具DLL。

    例如,以下是Visual Studio附帶的託管MSDataSetGenerator自定義工具的註冊信息:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\14.0\CLSID\{E76D53CC-3D4F-40A2-BD4D-4F3419755476}]
    @="COM+ class: Microsoft.VSDesigner.CodeGenerator.TypedDataSourceGenerator.DataSourceGeneratorWrapper"
    "InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
    "ThreadingModel"="Both"
    "Class"="Microsoft.VSDesigner.CodeGenerator.TypedDataSourceGenerator.DataSourceGeneratorWrapper"
    "Assembly"="Microsoft.VSDesigner, Version=14.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a"
    
  2. Generators\GUID下的所需Visual Studio配置單元中創建一個註冊表項,其中GUID是特定語言的項目系統或服務定義的GUID。密鑰的名稱將成為自定義工具的編程名稱。自定義工具鍵具有以下值:

    • (Default) - 可選。提供用戶友好的自定義工具說明。此參數是可選的,但建議使用。

    • CLSID - 必填。指定實現IVsSingleFileGenerator的COM組件的類庫的標識符。

    • GeneratesDesignTimeSource - 必需。指示此自定義工俱生成的文件中的類型是否可供可視設計器使用。對於視覺設計者不可用的類型,此參數的值必須為(零)0;對於可視設計者可用的類型,該參數的值必須為(1)1。

    請注意,您必須為希望自定義工具可用的每種語言單獨註冊自定義工具。

    例如, MSDataSetGenerator為每種語言註冊一次:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\14.0\Generators\{164b10b9-b200-11d0-8c61-00a0c91e29d5}\MSDataSetGenerator]
    @="Microsoft VB Code Generator for XSD"
    "CLSID"="{E76D53CC-3D4F-40a2-BD4D-4F3419755476}"
    "GeneratesDesignTimeSource"=dword:00000001
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\14.0\Generators\{fae04ec1-301f-11d3-bf4b-00c04f79efbc}\MSDataSetGenerator]
    @="Microsoft C# Code Generator for XSD"
    "CLSID"="{E76D53CC-3D4F-40a2-BD4D-4F3419755476}"
    "GeneratesDesignTimeSource"=dword:00000001
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\14.0\Generators\{e6fdf8b0-f3d1-11d4-8576-0002a516ece8}\MSDataSetGenerator]
    @="Microsoft J# Code Generator for XSD"
    "CLSID"="{E76D53CC-3D4F-40a2-BD4D-4F3419755476}"
    "GeneratesDesignTimeSource"=dword:00000001
    


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因