我在IIS中托管了WCF服务。目的是让客户进行调用并接收在另一个项目/ dll中定义的自定义类。我使用svcutil.exe生成了一个服务客户端。问题是这个自动生成的客户端包含我尝试从服务返回的类的新的部分/代理定义。它现在在编译时抛出我的原始自定义类和新的部分定义之间的转换错误。那么如何从WCF服务返回用户定义的类型?建议表示赞赏。
答案 0 :(得分:10)
如果您要从服务调用返回的类型未标记为DataContract
,则在未向客户端应用程序提供相同程序集的副本的情况下,您将无法从WCF返回该类型。< / p>
using System;
using System.ServiceModel;
[ServiceContract]
interface IService
{
[OperationContract]
TimeSpan GetTimeSpan();
}
class Service : IService
{
public TimeSpan GetTimeSpan() { return DateTime.Now.TimeOfDay; }
}
为什么之前的代码可以正常工作?这是有效的,因为服务调用的双方都有System.dll
,因此他们都知道System.TimeSpan
类型,它是OperationContract GetTimeSpan()
的返回类型。
以下是使用DataContract
:
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
[ServiceContract]
interface IService
{
[OperationContract]
Contract GetContract();
}
[DataContract]
class Contract
{
[DataMember]
public String MyProperty { get; set; }
}
class Service : IService
{
public Contract GetContract() { return new Contract(); }
}
现在,您已为已定义的类(Contract
)提供了序列化属性 - 这将允许您使用svcutil.exe
在客户端应用程序中创建将被序列化并发送到WCF服务。
现在,如果要返回不是DataContract
的类型,则必须向客户端应用程序提供包含该类型的程序集的副本。
答案 1 :(得分:4)
需要发生的事情之一是用户必须配置服务引用以使用DLL中的类型而不是代理定义的类 - http://msdn.microsoft.com/en-us/library/bb628653.aspx
答案 2 :(得分:4)
过去我们已经沿着这条路走下去了,问题当然是,这些是两个不同的类,所以你必须遵循@Rich Reuter提供的链接;
但是,我们已经了解了为什么这是不好的做法,因为它再次成为SOA的第三个原则 - “服务共享架构和合同,而不是类”。当然问题不仅仅是没有遵循某人在某个时候设定的“规则”,而是有充分的理由建议这一点 - 我们已经了解到服务与服务之间这种紧密耦合的代价。客户端意味着很难释放 - 如果服务需要向该类添加另一个字段,为另一个客户端提供服务 - 第一个客户端可能会受到影响;如果服务需要更改该类定义中的某些内容(以服务另一个客户端) - 第一个客户端将再次受到影响,反之亦然 - 客户端可能会影响服务的生命周期。
在大型项目中,这很快就会成为巨大的维护负担。
答案 3 :(得分:4)
我之前走过这条路,并且在某些方面希望我没有。可扩展性/自定义序列化 - 您必须非常小心。如果使用预卷序列化程序(例如protobuf-net(可以直接集成到WCF中,并且设计时考虑了可扩展性),则会更容易一些,但不容易。
实际上,共享类的一个优点是它使测试更容易一些:因为你到处都有相同的IFoo
,你可以模拟IFoo
有合理的成功机会。在代理涉及时(当您在测试代码和生产代码之间更改更多移动部分时)更难模拟。