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

How to keep some custom attributes when generating a proxy with svcutils?

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

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

以下class:

[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;
            }
        }        
}

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

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

IIRC,不过,WCF code-gen 确实 当你有多个属性时实际上会产生增量 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 中进行选择)。


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