WCF:接口,泛型和ServiceKnownType接口、WCF、ServiceKnownType

2023-09-02 01:48:07 作者:爱情总会有尽头//

我有以下几点:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

当我运行Get方法我收到以下错误:

When I run the Get method I get the following error:

有试图序列参数 http://tempuri.org/%3AGetResult 的错误。设置InnerException消息是'类型'PPS.Core.DomainModel.Support.Action.ActionResult`1 [PPS.Core.DomainModel.SportProgram.ISportProgram,PPS.Core.DomainModel,版本= 1.0.0.0,文化=中性公钥=空]数据合同名称'ActionResultOfanyType:http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action'预计不会。加不静态已知的已知类型的列表中的任何类型 - 例如,通过使用KnownTypeAttribute属性或通过将其添加到已知类型传递给DataContractSerializer的列表'。请参阅的InnerException了解更多详情。

There was an error while trying to serialize parameter http://tempuri.org/%3AGetResult. The InnerException message was 'Type 'PPS.Core.DomainModel.Support.Action.ActionResult`1[ [PPS.Core.DomainModel.SportProgram.ISportProgram, PPS.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

从这个错误我可以看到,它能够解决的ActionResult,但它并不能解决ISportProgram即使我有 ServiceKnownType(typeof运算(ActionResult的&LT; SportProgram>))我的服务接口...

From this error I can see that it can resolve ActionResult but it can't resolve ISportProgram even though I have ServiceKnownType(typeof(ActionResult < SportProgram >)) on my service interface...

请注意这是生成看起来像这样的参考存根,这样我就可以看到,已知类型被带到对面正确:

Note this is the Reference stub that is generated looks like this, so I can see that the known types are being brought across correctly:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

这是为什么怎么了????注意通过WCF服务的获取正确的...但它抛出时,返回的结果异常。

Why is this going wrong???? Note its getting through the WCF service correctly... but it throws the exception when the result is returned.

最后的ActionResult看起来是这样的:

Lastly ActionResult looks like this:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

干杯 安东尼

Cheers Anthony

推荐答案

嗯,我认为这就是SOA与面向对象的阻抗不匹配的另一个例子。这两个世界是相当不同的。

Well, I think this is another case of the SOA vs. OOP "impedance mismatch". The two world are quite separate.

在WCF中,所有正在从客户端传递到服务器被作为连载的消息 - 任何引用,使用

In WCF, all that is being passed from the client to the server is passed as serialized messages - no references are being used.

这意味着:一切要序列化的客户端上,它横跨发送到服务器,并反序列化,并用它在那里,必须具体的 - 你无法通过周围的接口,则不能使用不解决仿制药 - 你需要拼出来。基本上,所有这一切正在从客户端通过导线传递到服务器必须EX pressable XML模式。

This means: everything you want to serialize on the client, send it across to the server, and deserialize it and use it there, must be concrete - you cannot pass around interfaces, you cannot use "non-resolved" generics - you need to spell it out. Basically, all that's being passed from client over the wire to the server must be expressable in XML schema.

这有很多含义的:

在没有接口 - 你无法绕过的接口 - 你需要有具体类型的工作 在没有自动继承 - 你不能只是定义一个基类,并通过此基础上派生类的周围 - 那些需要specificied太(这是ServiceKnownType属性是什么) 在没有自动的仿制药 - 再次,你需要使用的具体类型而不是

这听起来像一个很大的限制 - 但它是因为WCF是使用所有基于消息的通信 - 它不能处理refereces,继承,泛型等等 - 你需要拼出来

This may sound like a lot of restrictions - but it's because WCF is using all message-based communication - it cannot deal with refereces, inheritance, generics etc. - you need to spell it out.

所以,我真的没有一个答案,你本身 - 我只是觉得你需要重新考虑你的策略和改变你的客户端和服务器通过WCF交换信息的方式。

So I don't really have an answer for you per se - I just think you need to rethink your strategy and change the way your client and server are exchanging information over WCF.

马克·

PS:我做了一些调查研究,并出乎大家我的理解,似乎有一种序列化什么,是基于跨线接口和/或抽象基类的,只要你能确定它的永远只有.NET导线的两端(即它的不可以互操作,例如Java的)。

PS: I did some more research, and contrary to all my understanding, there seems to be a way to serialize anything that's based on an interface and/or abstract base class across the wire, as long as you can be sure it's always only .NET on either end of the wire (i.e. it's not interoperable with e.g. Java).

请参阅亚伦Skonnard博客文章的NetDataContractSerializer 并另一个博客文章和yet另一个展示了如何使用NetDataContractSerializer要能够绕过像 IPerson 作为参数传递给你的方法。

See Aaron Skonnard blog post on the NetDataContractSerializer and another blog post and yet another showing how to use the NetDataContractSerializer to be able to pass around things like IPerson as parameters to your methods.