本文介绍了通用ServiceContract的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
[ServiceContract]
public interface ISecurities< T> :IPolicyProvider其中T:EntityObject
{
[OperationContract(Name =GetAllSecurities)]
IEnumerable< T> GetSecurities();
[OperationContract]
IEnumerable< T> GetSecurities< T1>(List< T1> lstIdentifiers)其中T1:FI_CusipMaster;
[OperationContract]
T GetSecurity< T1>(T1 lstIdentifiers)其中T1:FI_CusipMaster;
}
// Host
/// CADIS合约
ServiceHost dmHost = new System.ServiceModel.ServiceHost(typeof(GlobalInvestors.FIPA.BLL.UDI.CADISSecurities ));
Uri baseAddress = dmHost.BaseAddresses [0];
Uri policyAddress = new Uri(baseAddress.AbsoluteUri.Replace(baseAddress.AbsolutePath,));
dmHost.AddServiceEndpoint(
typeof(GlobalInvestors.FIPA.BLL.IPolicyProvider),
new System.ServiceModel.WebHttpBinding(),
policyAddress).Behaviors.Add (new System.ServiceModel.Description.WebHttpBehavior());
dmHost.Open();
//App.Config
< service behaviorConfiguration =UDIBehaviourname =GlobalInvestors.FIPA.BLL.UDI.CADISSecurities>
< endpoint binding =basicHttpBindingcontract =GlobalInvestors.FIPA.BLL.UDI.ICADISSecurities/>
<主机>
< baseAddresses>
< add baseAddress =http:// localhost:1667 / CADIS/>
< / baseAddresses>
< / host>
< / service>
< behavior name =UDIBehaviour>
< serviceMetadata httpGetEnabled =true/>
< serviceDebug includeExceptionDetailInFaults =true/>
< /行为>
[ServiceContract]
[ServiceKnownType(typeof(SecurityMasterAdapter))]
public interface ICADISSecurities:ISecurities< SecurityMasterAdapter>
{
}
我得到InvalidDataContractException Type系统.Collections.Generic.List`1 [T1]'不能作为模式类型导出,因为它是一个开放的泛型类型。如果泛型类型的所有泛型类型都是实际类型,则只能导出泛型类型。如果我主持这个合同。
我已经读过,避免在ServiceContract中使用泛型是很好的做法。但有可能使用T吗?解决方案
在这种情况下,您的问题不是T在ServiceContract中,而是用作DataContract的T1。如果在服务合同实施期间用特定类型替换T,则可以在服务合同中使用T.对于数据合约(操作参数和返回类型),您根本不能使用T.你总是必须指定具体的类型。可以使用ServiceKnownTypeAttribute重写您的服务契约,以便用FI_CusipMaster替换T1,并且ServiceKnownType指定从FI_CusipMaster派生的所有可能的类。
编辑:另一种方法是不使用ServiceKnownType并使用必须在FI_CusipMaster类型上定义的KnownTypeAttribute。
最好的问候,Ladislav
[ServiceContract]
public interface ISecurities<T> : IPolicyProvider where T: EntityObject
{
[OperationContract(Name="GetAllSecurities")]
IEnumerable<T> GetSecurities();
[OperationContract]
IEnumerable<T> GetSecurities<T1>(List<T1> lstIdentifiers) where T1 : FI_CusipMaster;
[OperationContract]
T GetSecurity<T1>(T1 lstIdentifiers) where T1 : FI_CusipMaster;
}
//Host
///CADIS Contract
ServiceHost dmHost = new System.ServiceModel.ServiceHost(typeof(GlobalInvestors.FIPA.BLL.UDI.CADISSecurities));
Uri baseAddress = dmHost.BaseAddresses[0];
Uri policyAddress = new Uri(baseAddress.AbsoluteUri.Replace(baseAddress.AbsolutePath, ""));
dmHost.AddServiceEndpoint(
typeof(GlobalInvestors.FIPA.BLL.IPolicyProvider),
new System.ServiceModel.WebHttpBinding(),
policyAddress).Behaviors.Add(new System.ServiceModel.Description.WebHttpBehavior());
dmHost.Open();
//App.Config
<service behaviorConfiguration="UDIBehaviour" name="GlobalInvestors.FIPA.BLL.UDI.CADISSecurities">
<endpoint binding="basicHttpBinding" contract="GlobalInvestors.FIPA.BLL.UDI.ICADISSecurities" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:1667/CADIS" />
</baseAddresses>
</host>
</service>
<behavior name="UDIBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
[ServiceContract]
[ServiceKnownType(typeof(SecurityMasterAdapter))]
public interface ICADISSecurities :ISecurities<SecurityMasterAdapter>
{
}
I get "InvalidDataContractException Type 'System.Collections.Generic.List`1[T1]' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types." if I host this contract.
I have read that it is good to avoid generics in ServiceContract. but is it possible to use T?
解决方案
Your problem in this case is not T in ServiceContract but T1 used as DataContract. You can use T in service contract if you replace T with specific type during service contract implementation. For data contracts (operation parameters and return types) you can't use T at all. You always have to specify concrete type. Your service contract can be rewritten with usage of ServiceKnownTypeAttribute so that T1 is replaced with FI_CusipMaster and ServiceKnownType specifies all possible classes derived from FI_CusipMaster.
Edit: Another way is not to use ServiceKnownType and use KnownTypeAttribute which has to be defined on FI_CusipMaster type.
Best regards, Ladislav
这篇关于通用ServiceContract的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!