使用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类可以供开发者比较清楚地使用枚举类型的成员了。
    在这里插入图片描述
    在这里插入图片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章