使用 svcutils 生成代理时如何保留一些自定义属性?

Posted

技术标签:

【中文标题】使用 svcutils 生成代理时如何保留一些自定义属性?【英文标题】:How to keep some custom attributes when generating a proxy with svcutils? 【发布时间】:2017-06-13 07:47:16 【问题描述】:

我使用以下命令为 WCF 服务生成代理类:

svcutil.exe" /out:C:\SomePath\.... /n:*,Internal.FooNameSpace 
   http://localhost/MyService.svc

以下类:

[ProtoContract]
[ServiceContract]
public class Foo 

    [ProtoMember(1)]
    [DataMember(Order = 0)]
    public string Bar  get; set; 

变成:

public partial class Foo : object, System.Runtime.Serialization.IExtensibleDataObject
            
        private string BarField;

        [System.Runtime.Serialization.DataMemberAttribute()]
        public string Bar
        
            get
            
                return this.BarField;
            
            set
            
                this.BarField = value;
            
                

有没有办法在生成的类上保留一些特定的属性? (例如:ProtoMember 在这种情况下)。我当然可以破解代理,但它会产生维护问题。

【问题讨论】:

你是对的,这并不是生成的。我在匿名代理时犯了一些错误。我编辑了问题。 我可能还需要一杯咖啡。感谢您的回答,我正在阅读。 即将添加另一个选项... 【参考方案1】:

如果您将其添加为服务引用,那么不行:无法保留该信息 - 它根本不在 WCF 端点中。

IIRC,不过,WCF 代码生成 确实 当您有多个属性时,WCF 代码生成实际上会提供增量 Order 值 - 即下一个属性将是 [System.Runtime.Serialization.DataMemberAttribute(Order = 1)],然后是 2 等. 所以一种选择是在不同的文件中partial class 的美妙之处),定义(在同一个命名空间等)关于你的类型的附加信息:

[ProtoContract(DataMemberOffset = 1)]
public partial class Foo  

这意味着:在处理[DataMember] 时,将1 添加到每个值 - 这意味着您应该获得所需的 1,2,3,4... 并且一切都会没问题,您不必更改代码。

或者,你可以是明确的:

[ProtoContract]
[ProtoPartialMember(1, nameof(Foo.Bar))]
[ProtoPartialMember(2, nameof(Foo.AnotherProp))]
public partial class Foo  

这使您可以更灵活地指定属性的细微差别。

作为另一种选择,您可以在运行时配置所有内容:

RuntimeTypeModel.Default.Add(typeof(Foo), false)
    .Add(1, nameof(Foo.Bar))
    .Add(2, nameof(Foo.AnotherProp));
    // or AddField to get the ValueMember that you can use to set
    // fine-grained control

最后,您可以发送数据协定 dll,并告诉 svctil 使用它已经包含的类型。您可以使用/reference:<file path> 命令行开关来执行此操作,或者在使用 UI 工具时有一个类似的功能(允许您从可用的 dll 中进行选择)。


作为第二个“终于”(因为一个还不够):您可以将数据描述为 .proto 模式,并告诉接收者在本地进行代码生成并告诉 svcutil 排除它(/excludeType:/reference:)。请注意,in progress rewrite of "protogen"目前不包含[DataContract]/[DataMember] 属性,但如果有用的话,我可以在今天得到它。

【讨论】:

关于DataMemberOffset 的解决方案:我必须用[DataContract] 属性装饰部分类才能使其工作。只有[ServiceContract] 它不起作用(序列化程序返回一个空字节数组) @tigrou 很公平;我假设(似乎是错误的)Foo 已经被标记为[DataContract]

以上是关于使用 svcutils 生成代理时如何保留一些自定义属性?的主要内容,如果未能解决你的问题,请参考以下文章

WCF:Svcutil 生成无效的客户端代理、Apache AXIS Web 服务、重载操作

WCF通过SVCUtil.exe生成客户端代理类和配置文件(转)

svcutil 不生成配置文件

无法在 Mono 中编译 svcutil 生成的 C#

svcutil.exe 未为 minOccurs=0 生成指定字段

在 SvcUtil 和 WSDL 代码生成期间抓取 KnownType 属性