OperationContracts
WCF REST サービスのジェネリック型パラメーターでインターフェイス型を返すにはどうすればよいですか? T
より具体的には、1 つの操作では機能しますが、インターフェイスであるジェネリックを使用して 2 番目の操作を追加すると機能しません。
要求と応答の形式として JSON を使用し、必要なデータの JSON 応答を解析する非 WCF クライアントにフィードします。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();
}
これら 2 つの一般的な結果が正常に機能することを指摘するために、例を残しましたが、明らかにそれらは具象型GetCount()
です。GetDescription()
そして、インターフェイスがどこにあるかGetFooData()
の 2 番目のメソッドを追加するまでは、問題なく動作します。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()
そして、ブラウザから呼び出したときのエラーメッセージ:
タイプ 'ServiceResult`1[IBarData]' は既知のタイプのリストに追加できません。 同じデータ コントラクト名を持つ別の型 'ServiceResult`1[IFooData]' 「http://schemas.datacontract.org/2004/07/ServiceResultOfanyType」は すでに存在します。
List<Test>
エラー メッセージの残りの部分は、コレクション型との衝突に関する注意書きですがTest[]
、ここでは当てはまりません。
明らかに、IFooData
とIBarData
は同じではなく、それらを実装するクラスも同じではありません。
では、なぜServiceResult<IFooData>
とServiceResult<IBarData>
の両方が に解決されるのServiceResultOfanyType
でしょうか?
何か足りないのですか、それともこれを修正する方法はありませんか?