Wcf 服务库接口类型未公开
Wcf Service Library interface type not being exposed
关于我遇到的问题,我看了很多例子(包括Passing Interface in a WCF Service?),但直到现在还没有找到解决办法。我有一个 Wcf 服务库 (.NET 4.0),其中包含以下内容
public class Service : IService
{
public bool Ping(IChannelManager channelManager)
{
return channelManager.Ping();
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
bool Ping(IChannelManager channelManager);
}
[ServiceContract]
[ServiceKnownType(typeof(TestChannelName))]
public interface IChannelManager
{
[OperationContract]
bool Ping();
}
[DataContract]
public class TestChannelName : IChannelManager
{
public bool Ping()
{
//perform a ping
return true;
}
}
我的项目编译正常。但是当我尝试从控制台应用程序将其添加为服务引用时,我可以很好地添加它并尝试访问如下方法;
using (Test.ServiceClient oClient = new Test.ServiceClient())
{
oClient.Ping();
}
但我遇到的问题是 Wcf 服务上的 Ping() 方法,接口类型作为对象 channelmanager 出现?喜欢
我尝试将 [ServiceKnownType(typeof(TestChannelName ))] 添加到两个接口,但没有成功。
我哪里错了?
我的回答将分为两部分 - 对为什么会发生这种情况的技术概述 - 以及为什么会发生这种情况的哲学思考。
首先从技术上讲如果你看一下:
http://localhost:8733/Design_Time_Addresses/YourProject/Service1/?singlewsdl
根据您的示例代码创建的 wsdl 文件,您会发现以下内容:
<xs:element name="Ping">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="channelManager" nillable="true" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
超过 mex 或如您在上面的 wsdl 中所见。你得到 xs:anytype
(实际上是 c# 对象)。这种行为虽然令人沮丧,但在意料之中,Mex 和 WsdlExtractor
只理解具体类型 - DataMembers 在服务参数中由 [DataContract]
表示,或者简单类型。任何其他的都将被优雅地视为 'object' 而不是编译失败。
哲学部分:
实际上,您正在尝试将方法 [ServiceContract]
作为参数传递。服务(在某些 DLL 中将其逻辑构建到 IL)不会序列化并通过网络传递 - 不是因为它无法完成 - 因为这不是它们的目的。
在您的示例中 IChannelManager
是 [ServiceContract]
,您甚至尝试将 Ping()
导出为 [OperationContract]
。 [ServiceKnownType]
属性对此无能为力。
[ServiceKnownType]
什么时候有用?好吧,这很好 documented 但它的要点是 - 如果你的 DataMember 在运行时要保存一些具体的 class - 编译器无法在编译时推断(例如接口,抽象 class es 或 base classes) 那么反序列化器将无法猜测在尝试反序列化时它应该 知道 的具体类型。
然后你可能会对我说 - 听起来不错,但我需要将我的逻辑(服务)作为参数传递。对此我要说的是——你需要的是重新设计你的解决方案。也许编写和托管更多服务并使用与 Strategy or Delegation 模式等效的服务。
我希望这对您有所帮助。
关于我遇到的问题,我看了很多例子(包括Passing Interface in a WCF Service?),但直到现在还没有找到解决办法。我有一个 Wcf 服务库 (.NET 4.0),其中包含以下内容
public class Service : IService
{
public bool Ping(IChannelManager channelManager)
{
return channelManager.Ping();
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
bool Ping(IChannelManager channelManager);
}
[ServiceContract]
[ServiceKnownType(typeof(TestChannelName))]
public interface IChannelManager
{
[OperationContract]
bool Ping();
}
[DataContract]
public class TestChannelName : IChannelManager
{
public bool Ping()
{
//perform a ping
return true;
}
}
我的项目编译正常。但是当我尝试从控制台应用程序将其添加为服务引用时,我可以很好地添加它并尝试访问如下方法;
using (Test.ServiceClient oClient = new Test.ServiceClient())
{
oClient.Ping();
}
但我遇到的问题是 Wcf 服务上的 Ping() 方法,接口类型作为对象 channelmanager 出现?喜欢
我尝试将 [ServiceKnownType(typeof(TestChannelName ))] 添加到两个接口,但没有成功。
我哪里错了?
我的回答将分为两部分 - 对为什么会发生这种情况的技术概述 - 以及为什么会发生这种情况的哲学思考。
首先从技术上讲如果你看一下:
http://localhost:8733/Design_Time_Addresses/YourProject/Service1/?singlewsdl
根据您的示例代码创建的 wsdl 文件,您会发现以下内容:
<xs:element name="Ping">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="channelManager" nillable="true" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
超过 mex 或如您在上面的 wsdl 中所见。你得到 xs:anytype
(实际上是 c# 对象)。这种行为虽然令人沮丧,但在意料之中,Mex 和 WsdlExtractor
只理解具体类型 - DataMembers 在服务参数中由 [DataContract]
表示,或者简单类型。任何其他的都将被优雅地视为 'object' 而不是编译失败。
哲学部分:
实际上,您正在尝试将方法 [ServiceContract]
作为参数传递。服务(在某些 DLL 中将其逻辑构建到 IL)不会序列化并通过网络传递 - 不是因为它无法完成 - 因为这不是它们的目的。
在您的示例中 IChannelManager
是 [ServiceContract]
,您甚至尝试将 Ping()
导出为 [OperationContract]
。 [ServiceKnownType]
属性对此无能为力。
[ServiceKnownType]
什么时候有用?好吧,这很好 documented 但它的要点是 - 如果你的 DataMember 在运行时要保存一些具体的 class - 编译器无法在编译时推断(例如接口,抽象 class es 或 base classes) 那么反序列化器将无法猜测在尝试反序列化时它应该 知道 的具体类型。
然后你可能会对我说 - 听起来不错,但我需要将我的逻辑(服务)作为参数传递。对此我要说的是——你需要的是重新设计你的解决方案。也许编写和托管更多服务并使用与 Strategy or Delegation 模式等效的服务。
我希望这对您有所帮助。