我有一个关于WCF大师的新问题。
所以,我有一个类User
,它接近我用于数据库操作的DB的'User'表示。现在,我希望有两个不同的服务合同,使用这个类作为数据合同,但每个都以他们自己的方式......我的意思是,
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'
作为数据库操作,我可以选择实现这一目标吗?我真的需要创建不同的数据合同还是有另一种更聪明的方式?
最好不仅要给我解决方案,还要向我解释一些最佳实践和替代方案。
提前谢谢。
EDIT1: 我在这里添加了一个虚拟DBLayer类,以便更好地概述,以及为什么我认为在这种情况下继承可能不太好。
解决方案是将另一个“UserForService1
”和“UserForService2
”作为数据合同,这些合同最终会从/ {User
'映射,但我想要其他一些观点。
EDIT2:在这种情况下帮助我的非常好的文章:http://bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx
答案 0 :(得分:4)
您可以为每项服务创建单独的DTO,但您的案例实际上非常适合Decorator pattern:
[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类似的代码,只公开你关心的内容......
答案 1 :(得分:1)
如果它们旨在表示不同类型的用户,则它们应该是不同的类。我同意评论中的phoog,你应该从共享的User类派生你想要的类型,并将特定的服务属性添加到派生类。
为什么你不认为继承在这种情况下会好?如果您向我们提供更多详细信息,我们可以尝试修改建议以适合您的实际问题。
答案 2 :(得分:1)
根据评论中的建议,您可以使用基本用户派生两个类,然后使用Data Contract Known Types,您可以实现所需的目标。有关更多示例,请参阅以下链接。
http://www.freddes.se/2010/05/19/wcf-knowntype-attribute-example/
答案 3 :(得分:1)
如果您不想使用继承,请执行以下操作:
[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消息为null时,执行:
[DataMember(EmitDefaultValue=false)]
然后当该属性为null时,它不会包含在序列化中。如果客户端是从WSDL生成的,那将没有什么区别,因为它的User类型仍然必须包含这两个属性。它只会改变序列化,而不是像客户端那样发送客户端:
<User>
<PropertyVisibleOnlyForService1 nil="true" />
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
它会发送:
<User>
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>