使用CrmSvcUtil.exe創建代碼生成工具擴展選項集的代碼生成,並解決UnknownLabel命名的問題

使用CrmSvcUtil.exe創建代碼生成工具擴展選項集的代碼生成,並解決UnknownLabel命名的問題

關於CrmSvcUtil.exe工具

我們知道CrmSvcUtil.exe 是用於 Microsoft Dynamics 365(在線或本地) 的一個命令行代碼生成工具。 該工具可生成表示 Microsoft Dynamics 365 使用的實體數據模型的前期綁定 .NET Framework 類。
下載方法:Download tools from NuGet

  1. 在內部部署版本里可以使用以下命令生成代碼
CrmSvcUtil.exe /url:http://d365opServer:5555/Dynamics365/XRMServices/2011/Organization.svc    /out:AllEntitiesOP.cs /username:simonsh /password:XXXXXX /domain:d365op.net    /namespace:net.mymuch

隨即會生成所有Entity的早期類。導入到VS解決方案中即可使用。
在這裏插入圖片描述

  1. 在Online版本里可以使用以下命令生成代碼
CrmSvcUtil.exe /url:https://XXX.api.crm.dynamics.com/XRMServices/2011/Organization.svc    /out:AllEntitiesOnline.cs /username:simonsh@XXXX.com /password:XXXXX /namespace:net.mymuch

Dynamics365 Online版本加載的功能如果比較多的話,這個cs文件會比較大。
在這裏插入圖片描述
在這裏插入圖片描述

創建用於代碼生成工具的擴展

以上操作雖然可以生成所有Entity的早期類,但是當遇到一些特殊情況,無法滿足編程的需求,這個時候就要對Entity以外的內容進行擴展。CrmSvcUtil.exe工具還有另外一部分擴展參數可以使用。

參數名稱 接口名稱 說明
/codecustomization ICustomizeCodeDomService 在 CodeDOM 生成完成後調用,假定爲 ICodeGenerationService 的默認實例。 這對生成其他類(如選擇列表中的常量)很有用。
/codewriterfilter ICodeWriterFilterService 在 CodeDOM 生成過程中調用(假定爲 ICodeGenerationService 的默認實例),以確定是否應生成特定對象或屬性。
/codewritermessagefilter ICodeWriterMessageFilterService 在 CodeDOM 生成過程中調用(假定爲 ICodeGenerationService 的默認實例),以確定是否應生成特定消息。 由於 Microsoft.Crm.Sdk.Proxy.dll 和 Microsoft.Xrm.Sdk.dll 中已生成消息,因此不應將其用於請求/響應。
/metadataproviderservice IMetadataProviderService 調用以從服務器中檢索元數據。 在生成過程中可能多次調用此參數,所以應緩存數據。
/codegenerationservice ICodeGenerationService CodeDOM 生成的核心實現。 如果發生更改,其他擴展可能無法按所述方式工作。
/namingservice INamingService 在 CodeDOM 生成過程中調用,以確定對象的名稱(假定爲默認實現)。

通過指定以上這些命令行參數和參數值,可以擴展代碼生成工具的功能。 若要指定參數,請向命令行中添加以下內容:/<參數名稱>:<類名稱>,<程序集名稱>。 請注意,程序集名稱不包括 .dll 擴展名。 作爲替代方式,也可以採用""的格式向配置文件中添加等效值。
詳見官方說明:Create extensions for the code generation tool

  1. 生成擴展的準備工作
    以下我們以生成選項集的cs類爲例,首先需要找到Dynamics 365 CRM SDK 8.X版本下載,然後找到SampleCode\CS\CrmSvcUtilExtensions,裏面有兩個工程進行編譯。因爲是8.X的版本,如果要適用到9.X的CRM中,需要對工程的引用進行更新後再編譯。
    在這裏插入圖片描述
  2. 編譯完後,把兩個DLL文件拷貝到跟CrmSvcUtil.exe工具同級目錄下
    在這裏插入圖片描述
  3. CMD中執行以下命令,具體參數可以根據自己的需要進行修改。
CrmSvcUtil.exe /codewriterfilter:"Microsoft.Crm.Sdk.Samples.FilteringService,GeneratePicklistEnums" /codecustomization:"Microsoft.Crm.Sdk.Samples.CodeCustomizationService,GeneratePicklistEnums" /namingservice:"Microsoft.Crm.Sdk.Samples.NamingService,GeneratePicklistEnums" /url:https://XXXX.api.crm.dynamics.com/XRMServices/2011/Organization.svc /out:OptionSets.cs /username:simonsh@XXXX.com /password:XXXXXX /namespace:net.mymuch

在這裏插入圖片描述

  1. 生成的代碼
    在這裏插入圖片描述

  2. 找到自定義的選項集
    在這裏插入圖片描述

  3. 這裏發現了問題,自動生成的名字是UnknownLable開頭的,這就有點不爽了。
    我的選項集定義是這樣的:
    在這裏插入圖片描述
    如果選項集的內容是英文的,會是正常的。
    在這裏插入圖片描述
    那麼對於中文定義的選項集內容就沒有辦法了嗎?

解決命名爲UnknownLabel的問題

  1. 首先導致這個UnknownLabel的原因是因爲CrmSvcUtil.exe工具裏引用到的方法不支持中文等Unicode字符爲命名的變量,當然當下不管是C#還是java雖然都已經支持了中文的變量,但是這樣做不合規矩。
    在這裏插入圖片描述

  2. 解決的思路有下面的幾種:
    一, 如果你的多語言支持中有英文的,可以切換dynamics365 的語言爲英文,定義的選項集自然爲英文,這個時候可以正常輸出變量。當然沒有英文支持的就悲劇了。
    二,可以藉助第三方工具DDL,把取到的label的中文值轉換成拼音。
    三,統一自定義選項集的命名規則,可以填寫外部值來命令對應的英文。

  3. 這裏我們選擇使用第三種思路,先修改自定義選項集的外部值,爲什麼選擇外部值這個屬性,我在最後會作說明。
    在這裏插入圖片描述

  4. 修改官方sample代碼,如果名字中包含UnknownLabel字符並且外部值被定義的話,則用外部值代替。編譯好後,複製DLL到CrmSvcUtil.exe的同級目錄。
    在這裏插入圖片描述

        /// <summary>
        /// Handles building the name for an Option of an OptionSet.
        /// </summary>
        public string GetNameForOption(OptionSetMetadataBase optionSetMetadata,
            OptionMetadata optionMetadata, IServiceProvider services)
        {
            var name = DefaultNamingService.GetNameForOption(optionSetMetadata,
                optionMetadata, services);
            // 如果名字中包含UnknownLabel字符的
            if (name.Contains("UnknownLabel"))
            {
                // 如果外部值不爲空
                if (optionMetadata.ExternalValue != null && !optionMetadata.ExternalValue.Equals(""))
                {
                    // Name設置爲外部值
                    name = optionMetadata.ExternalValue;
                }
            }
            Trace.TraceInformation(String.Format("The name of this option is {0}",
                name));
            name = EnsureValidIdentifier(name);
            name = EnsureUniqueOptionName(optionSetMetadata, name);
            return name;
        }
  1. 執行剛纔的命令
    在這裏插入圖片描述
  2. 這是自動生成代碼中的這個選項名字就用外部值替換了。
    在這裏插入圖片描述
  3. 另外,爲什麼選擇這個屬性,我查了一下官方文檔,沒有對這個外部值屬性做任何說明。可能是一種擴展屬性。至此,生成的cs類可以供開發者比較清楚地使用枚舉類型的成員了。
    在這裏插入圖片描述
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章