WCF - 使用完全相同的数据协定的多个服务协定
本文关键字:数据 服务 WCF | 更新日期: 2023-09-27 17:55:23
我有一个新问题要问WCF大师。
因此,我有一个类User
,它接近我用于数据库操作的数据库中的"用户"表示形式。现在,我希望有 2 个不同的服务协定将此类用作数据协定,但每个协定都有自己的方式......我的意思是
public class DBLayer
{
void InsertUsers(List<User> userList)
{
// both 'PropertyVisibleForService1' and 'PropertyVisibleForService2'
// are used HERE to be inserted into their columns
}
}
[DataContract]
public class User
{
[DataMember] public string PropertyVisibleOnlyForService1{...}
[DataMember] public string PropertyVisibleOnlyForService2{...}
}
[ServiceContract]
public interface IService1
{
List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
}
[ServiceContract]
public interface IService2
{
List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
}
因此,这个想法是每个服务都将获得不同类型的用户,即'User'
子集。请记住,我想像对数据库操作一样使用该'User'
,我有什么选择来实现这一点?我真的需要创建不同的数据协定还是有其他更聪明的方法?
最好不仅给我解决方案,而且还向我解释一些最佳实践和替代方案。
提前谢谢你。
编辑1:我在这里添加了一个虚拟的DBLayer类,以便更好地了解以及为什么我认为在这种情况下继承可能不好。
一个解决方案是将另一个"UserForService1
"和"UserForService2
"作为数据契约,它们将在末尾从/映射到"User
",但我想要一些其他观点。
编辑2:非常好的文章,在这种情况下帮助了我:http://bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx
您可以为每个服务创建单独的 DTO,但您的案例实际上是装饰器模式的理想选择:
[DataContract]
public class UserForService1 : User
{
private User mUser;
public UserForService1(User u)
{
mUser = u;
}
//expose only properties you'd like the user of this data contract to see
[DataMember]
public string SomeProperty
{
get
{
//always call into the 'wrapped' object
return mUser.SomeProperty;
}
set
{
mUser.SomeProperty = value;
}
}
// etc...
}
对于 Service2 类似的代码,它只公开你关心的东西......
如果它们旨在表示不同类型的用户,则它们应该是不同的类。我同意注释中的phoog,您应该从共享User类派生所需的类型,并将特定的服务属性添加到派生类中。
在这种情况下,您为什么不认为继承会很好?如果您向我们提供更多详细信息,我们可以尝试修改建议以适合您的实际问题。
如注释中所建议的,您可以从基本用户派生两个类,然后使用数据协定已知类型,您可以实现所需的目标。有关更多示例,请参阅以下链接。
http://www.freddes.se/2010/05/19/wcf-knowntype-attribute-example/
http://footheory.com/blogs/bennie/archive/2007/07/28/handling-data-contract-object-hierarchies-in-wcf.aspx
如果您不想使用继承,如下所示:
[DataContract]
public class User
{
}
[DataContract]
public class Service1User : User
{
[DataMember] public string PropertyVisibleOnlyForService1{...}
}
[DataContract]
public class Service2User : User
{
[DataMember] public string PropertyVisibleOnlyForService2{...}
}
[ServiceContract]
public interface IService1
{
List<Service1User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
}
[ServiceContract]
public interface IService2
{
List<Service2User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
}
那我不确定你会怎么做。在这一点上,您有点破坏类型声明的主体。以正常的 .NET 方式考虑它;如果在应用程序中定义"用户",则它在任何地方都是相同的类型。某些属性无法对某些其他类或方法隐藏。
WCF 还将把此类型信息打包到生成的 WSDL 中,并且它只定义一次 User 类型,因此它需要知道有哪些属性。
现在,如果您关心的只是构造的实际 SOAP 消息,而不关心 WSDL 或从 WSDL 生成的任何客户端将看到的内容,那么从技术上讲,您可以让它在 SOAP 消息为空时不将该属性发出到 SOAP 消息中,方法是执行以下操作:
[DataMember(EmitDefaultValue=false)]
然后,当该属性为 null 时,它将不会包含在序列化中。但是,如果客户端是从 WSDL 生成的,则不会产生真正的区别,因为它的用户类型仍然必须包含这两个属性。它只会更改序列化,以便而不是向客户端发送类似的东西:
<User>
<PropertyVisibleOnlyForService1 nil="true" />
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
相反,它将发送:
<User>
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>