WCF:接口,型和ServiceKnownType
-
21-09-2019 - |
题
我有以下几种:
[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl
{
[OperationContract]
IActionResult<ISportProgram> Get(IActionParameters parameters);
}
当我运行得到方法,我得到的以下错误:
有一个错误的话,试图化参数 http://tempuri.org/:GetResult.内部消息是'Type'PPS。核心。DomainModel.支持。行动。ActionResult`1[[PPS。核心。DomainModel.SportProgram.ISportProgram,PPS。核心。DomainModel,Version=于1.0.0.0、文化=中立的,程序=null]]'与数据的合同名称'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action'不是预期。添加任何类型不知静态的清单已知类型--例如,通过使用KnownTypeAttribute属性或通过它们添加到名单的已知类型的传递给DataContractSerializer.'.请参阅InnerException的更多详细信息。
从这个错误我可以看到,它可以解决ActionResult但它不能解决ISportProgram即使我有 ServiceKnownType(类型(ActionResult < SportProgram>)) 在我的服务接口...
注意,这是参照根产生看起来像这样,这样我就可以看到,已知类型正在带来的全正确:
[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服务正确...但它抛出异常的结果是返回。
最后ActionResult看起来是这样的:
public interface IActionResult<T>
{
T Result { get; set; }
}
欢呼 安东尼
解决方案
嗯,我认为这是另一种情况下SOA与面向对象"不匹配".两个世界是相当分开的。
在WCF,所有这一切都是正在通过从该客户向服务器传递的 化的消息 -没有文献均被使用。
这意味着:一切你想要列化上的客户,发送给该服务器,并deserialize和使用它还必须 混凝土 -你不能通过周围的接口,不能使用"非解决"仿制药-你需要拼出来。基本上,这是通过从客户的在线服务器必须expressable在XML模式。
这有很多的影响:
- 没有接口-你不能通过围绕口的-你需要与具体类型
- 没有"自动"承-你不能只是定义的一个基类,并通过周围的衍生出类的基础上就那些需要specificied过(这是什么ServiceKnownType属性为)
- 没有自动泛型的再次,需要使用具体的类型而不是
这听起来可能像一个很大的限制,但这是因为WCF使用的所有消息-通信-它不能处理refereces、继承、泛型等。-你需要拼出来。
所以我真的没有一个答案为你本身-我只是觉得你需要重新考虑你的策略和改变你的客户和服务器交流信息的过WCF。
Marc
PS:我做了一些更多的研究,并违反了我所有的了解,似乎有一种方法来serialize任何基于一个接口和/或抽象的基类跨线,只要作为你可以确信这是唯一的。净两端的线(即它的 不 可互操作的,例如Java)。
看看 亚伦Skonnard博客上张贴的NetDataContractSerializer 和另一个 博客 和 又一个 显示如何使用NetDataContractSerializer能够通过周围的东西喜欢 IPerson
作为参数,以你的方法。
其他提示
这是我与 ServiceStack.NET 解决的一个问题 - 我的开源.NET和MONO网站服务框架。
服务栈在很大程度上受马丁福勒斯数据传输对象模式的影响,因为它可以让你简单地使用DTO的定义Web服务 - 即SOA方式:。)
我避免此限制,通过生成自己的WSDL的,其行为正如你所期望的那样是在WCF固有的。作为替换WCF的复杂的配置/的ServiceContract模型的好处 - 在SOAP Web服务也适用于MONO - 的看到现场演示。
这是一个古老的问题和尽管所接受的回答是完全正确的,我stumpled应该在搜索一个类似的问题,并认为我可以分享我的经验。这是经常头痛,但它是能够使用仿制药组合与接口有WCF。这里有一个工作实例的另一个(类似的)执行情况,我已经做到:
[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
public interface IService :
{
[OperationContract]
ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);
}
public interface ICollectionWrapper<TModel>
{
int TotalCount { get; set; }
IEnumerable<TModel> Items { get; set; }
}
[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
[DataMember]
public int TotalCount { get; set; }
[DataMember]
public IEnumerable<TModel> Items { get; set; }
}
public class CompanyDto : IAssociation
{
public int Id { get; set; }
public string Name { get; set; }
}
public class OrganizationDto : IAssociation
{
public int Id { get; set; }
public string Name { get; set; }
}
这里的关键是结合使用 KnownType
和 ServiceKnownType
.
所以你的情况你可以做像这样的东西:
[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic.
public interface ISportProgramBl
{
[OperationContract]
IActionResult<ISportProgram> Get(IActionParameters parameters);
}
[KnownType(typeof(SportProgram))] // Actual implementation here.
public class ActionResult<T>
{
// Other stuff here
T FooModel { get; set; }
}
这将工作,如果你有一个共享合同(访问的实际服务界面)以及消费合同 ChannelFactory<ISportProgramBl>
.我不知道,如果它的工作与服务的参考。
然而,似乎有一些问题,与实现作为这里提到的:
和另一个类似的问题,并回答了这里:
您正在返回的IList T的它也许,该系统已发现问题T是什么。
不知道它是确定返回一个接口,而不是一种类型。
您在指定对象的接口和没有具体的类型?
PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>
编辑:
我说的是都是要传递的泛型的具体类型(包括通过接口的子对象)在已知类型列表中传递。我们已经在所有的类型都还不知道serialasation问题。