使用 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] 添加=] 如果有用的话。
我使用以下命令为 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] 添加=] 如果有用的话。