[英]WCF - Passing objects that are not declared as a ServiceKnownType
I have the following WCF interface that is exposed via net.tcp:我有以下通过 net.tcp 公开的 WCF 接口:
[ServiceContract]
public interface IMyWCFService
{
[OperationContract]
Response ProcessRequest(Request request);
}
This is driven by the following classes (much simplified for the purposes of this question):这是由以下类驱动的(为本问题的目的而进行了很多简化):
[Serializable]
public abstract class Message
{
[XmlAttribute]
public string Sender { get; set; }
[XmlAttribute]
public string Recevier { get; set; }
}
[Serializable]
public abstract class Response : Message
{
[XmlAttribute]
public int EventCode { get; set; }
}
[Serializable]
public abstract class Request : Message
{
[XmlAttribute]
public string SourceSystem { get; set; }
}
[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringRequest : Request
{
[XmlElement]
public string Payload { get; set; }
}
[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringResponse : Response
{
[XmlElement]
public string Payload { get; set; }
}
Note: We use XMLSerializer
rather than DataContractSerializer
as these classes have to be compatible with legacy systems that are .NET 2 based.注意:我们使用XMLSerializer
而不是DataContractSerializer
,因为这些类必须与基于 .NET 2 的遗留系统兼容。
As the interface uses the abstract Request/Response classes in the ProcessRequest method we have to declare StringResponse / StringRequest as ServiceKnownType
, for example:由于接口在 ProcessRequest 方法中使用抽象的 Request/Response 类,我们必须将 StringResponse / StringRequest 声明为ServiceKnownType
,例如:
[ServiceContract]
[ServiceKnownType(typeof(StringRequest))]
[ServiceKnownType(typeof(StringResponse))]
public interface IMyWCFService
{
[OperationContract]
ResponseMessage ProcessRequest(RequestMessage request);
}
This works perfectly and all is good in the world, however.....这完美无缺,世界上一切都很好,但是......
The WCF listener is just one component of a much larger framework and the classes described above are used throughout. WCF 侦听器只是更大框架的一个组件,上面描述的类贯穿始终。 We have also designed the framework to allow us to add new types of Request/Response messages with relative ease.我们还设计了框架以允许我们相对轻松地添加新类型的请求/响应消息。 For example I might add:例如,我可能会添加:
public class CustomRequest : Request
{
public MyCustomXmlSerialisableRequestObject Payload { get; set; }
}
public class CustomResponse: Response
{
public MyCustomXmlSerialisableResponseObject Payload { get; set; }
}
Which also works fine until I get the the WCF service interface.在我获得 WCF 服务接口之前,它也可以正常工作。 When we add a new custom request/response pair we also need to update the ServiceKnownType on the interface to include them.当我们添加一个新的自定义请求/响应对时,我们还需要更新接口上的 ServiceKnownType 以包含它们。 Which then means I have to redeploy the service.这意味着我必须重新部署服务。 So the question is - is there any way I can avoid having to update the interface?所以问题是 - 有什么办法可以避免更新界面?
As an example when we used remoting we could pass through any objects we liked as long as they were serialisable so I assume/hope that there is a similar solution in WCF.作为一个例子,当我们使用远程处理时,我们可以通过任何我们喜欢的对象,只要它们是可序列化的,所以我假设/希望在 WCF 中有类似的解决方案。
EDIT: Update编辑:更新
Following the guidance found here:按照此处的指导:
http://ashgeek.blogspot.com/2011/02/wcf-serialization-dynamically-add.html http://ashgeek.blogspot.com/2011/02/wcf-serialization-dynamically-add.html
I seem to be on the right track.我似乎走在正确的轨道上。 However when I update the client service reference it pulls in all the dynamically types into the service reference.但是,当我更新客户端服务引用时,它会将所有动态类型拉入服务引用中。 Which is undesirable as not all clients need to, or should, know about all messages that derive from Request/Response这是不可取的,因为并非所有客户端都需要或应该知道从请求/响应派生的所有消息
More importantly I seem to lose the the ServiceClient class that is used to push messages, eg:更重要的是,我似乎丢失了用于推送消息的 ServiceClient class,例如:
// Client proxy class goes AWOL after service reference update
var client = new MyServiceReference.Client();
var responseMessage = client.ProcessRequest(requestMessage)
At the beginning you are mentioning that you need compatibility with .NET 2.0 services but in the same time you are complaining that something which worked in .NET remoting doesn't work in WCF - you are limited by features possible with .NET 2.0 web services where both server and client must know about transferred types on the service layer = types must be in service description and WSDL. At the beginning you are mentioning that you need compatibility with .NET 2.0 services but in the same time you are complaining that something which worked in .NET remoting doesn't work in WCF - you are limited by features possible with .NET 2.0 web services where both server并且客户端必须知道服务层上传输的类型=类型必须在服务描述和 WSDL 中。 Moreover because you decided to use XmlSerializer you generally lost most of the ways how to achieve that:此外,由于您决定使用 XmlSerializer,您通常会丢失大多数实现该目标的方法:
ServiceKnowType
can load known types from static method ServiceKnowType
可以从 static 方法加载已知类型DataContractSerializer
) 配置中定义的 KnownTypes (需要DataContractSerializer
)DataContractSerializer
) DataContractResolver(仅 WCF 4)并在启动时加载所有派生类型(需要DataContractSerializer
)NetDataContractSerializer
and custom behavior) = generally this is the same functionality as in remoting and it demands sharing types between service and client and both service and client must be .NET application using WCF stuff. 在消息中传递 .NET 类型信息(需要NetDataContractSerializer
和自定义行为)= 通常,这与远程处理中的功能相同,它需要在服务和客户端之间共享类型,并且服务和客户端都必须是 .NET 应用程序,使用 ZFB608636129CB469BE67B7FE11。 With XmlSerializer
you have one option使用XmlSerializer
你有一个选择
XElement
and receive
XElement
in your service operation and deal with XML by yourselves
XElement
并接收
XElement
并自行处理 XML
Edit:编辑:
There is no dynamic behavior in service description.服务描述中没有动态行为。 It is created only once when the host starts and after that doesn't change until you restart the host.它仅在主机启动时创建一次,之后在您重新启动主机之前不会更改。 If you need subset of WSDL per client you need separate endpoint for each client and you must define exactly which data contracts should be exposed on each endpoint.如果您需要每个客户端的 WSDL 子集,您需要为每个客户端提供单独的端点,并且您必须准确定义应该在每个端点上公开哪些数据协定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.