如何在我的WCF REST服務中從OperationContracts
返回泛型類型參數中的接口類型?更具體地說,它適用於一個操作,但不適用於當我使用通用接口T
添加第二個操作時。WCF中帶接口類型參數的泛型返回類型
我使用JSON作爲請求和響應格式,提供一個非WCF客戶端來解析所需數據的JSON響應。我沒有使用SOAP或由服務生成的WSDL。
我的服務接口:
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(ServiceKnownTypesHelper))]
public interface IMyService
{
[WebGet(UriTemplate="count")]
[OperationContract]
IServiceResult<int> GetCount();
[WebGet(UriTemplate="desc")]
[OperationContract]
IServiceResult<string> GetDescription();
[WebGet(UriTemplate="foo")]
[OperationContract]
IServiceResult<IFooData> GetFooData();
// Fails when I invoke either method if I uncomment this operation.
//[WebGet(UriTemplate="bar")]
//[OperationContract]
//IServiceResult<IBarData> GetBarData();
}
我離開GetCount()
和GetDescription()
的例子指出,這兩個通用的結果做工精細,但很明顯,他們是具體類型。即使GetFooData()
工作正常,直到我添加第二種方法IServiceResult<T>
其中T
是一個接口。
GetFooData()
和GetBarData()
的返回類型不一樣,實現它們的具體類也不一樣。
你可以想像,我已經減少了實施的骨架,因爲我不認爲實行的是問題的心臟:
#region My service implementation
public class MyService : IMyService
{
public IServiceResult<int> GetCount()
{
return new ServiceResult<int>(42);
}
public IServiceResult<string> GetDescription()
{
return new ServiceResult<string>("Muffins");
}
public IServiceResult<IFooData> GetFooData()
{
return new ServiceResult<IFooData>(new FooData() { Foo = 99 });
}
public IServiceResult<IBarData> GetBarData()
{
return new ServiceResult<IBarData>(new BarData() { Bar = "Elvis was here" });
}
}
#endregion
#region ServiceKnownTypesHelper.GetServiceKnownTypes():
public static class ServiceKnownTypesHelper
{
private static IList<Type> serviceKnownTypes = new List<Type>()
{
typeof(FooData),
typeof(BarData),
typeof(ServiceResult<int>),
typeof(ServiceResult<string>),
typeof(ServiceResult<IFooData>),
typeof(ServiceResult<IBarData>),
};
public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider paramIgnored)
{
return serviceKnownTypes;
}
}
#endregion
#region IServiceResult<T> and its concrete implementation:
public interface IServiceResult<T>
{
IList<string> Errors { get; }
T Value { get; set; }
}
[DataContract]
public class ServiceResult<T> : IServiceResult<T>
{
public ServiceResult(T value)
{
this.Value = value;
}
private IList<string> errors = new List<string>();
[DataMember]
public IList<string> Errors
{
get
{
return this.errors;
}
}
[DataMember]
public T Value { get; set; }
}
#endregion
#region IFooData and its concrete implementation:
public interface IFooData
{
int Foo { get; set; }
}
[DataContract]
public class FooData: IFooData
{
[DataMember]
public int Foo { get; set; }
}
#endregion
#region IBarData and its concrete implementation:
public interface IBarData
{
string Bar { get; set; }
}
[DataContract]
public class BarData: IBarData
{
[DataMember]
public string Bar { get; set; }
}
#endregion
和錯誤消息時,我調用GetBarData()
從瀏覽器:
Type 'ServiceResult`1[IBarData]' cannot be added to list of known types since another type 'ServiceResult`1[IFooData]' with the same data contract name 'http://schemas.datacontract.org/2004/07/ServiceResultOfanyType' is already present.
錯誤消息的其餘部分是一個紅色的鯡魚約碰撞集合類型List<Test>
和Test[]
,這是不是這裏的情況。
很明顯,IFooData
和IBarData
是不一樣的,也沒有實現它們的類。
那麼爲什麼ServiceResult<IFooData>
和ServiceResult<IBarData>
都解決爲ServiceResultOfanyType
?
我錯過了什麼,或者有沒有辦法解決這個問題?
到目前爲止,我發現的唯一解決方法是將通用ServiceResult類型平鋪到一組固定的「ServiceResultOfIFooData:ServiceResult 」類中,並將OperationContracts更改爲返回這些類型。這讓我感到不舒服,因爲它首先違反了仿製藥的目的。 –
JMD
2013-03-28 18:32:01
我試過[覆蓋DataContract的名稱](http://msdn.microsoft.com/en-us/library/ms731045(v = vs.100).aspx)ServiceResult使用'[DataContract(Name =「) ServiceResultOf {0}「)]'但{0}仍然解析爲」anyType「,回想起來,這是令人失望的,但並不是完全沒有預料到的,因爲這可能正是默認情況下當Name不被覆蓋時正在做的事情。 –
JMD
2013-03-28 22:07:41
偉大的問題。我有同樣的問題,真的想避免使用具體的類。您是否可能找到另一種解決方案,而不是接受答案中提到的解決方案? – smoksnes 2016-02-12 08:56:14