2016-09-09 12 views
1

この質問は再び繰り返されます。これは.NETやSilverlightでは問題ではありませんでしたが、それ以来、私は決して既知の型をServiceContractに物理的に入力することなく指定する方法を見たことがありません。つまり、実行時にこのリストを動的に変更することはできません。これはXamarin、UWP、そしておそらく他のプラットフォームの問題です。だから、これを見てみましょう。WCF - 既知のタイプを指定する(PCL/.NET標準)

もともと、.NETおよびSilverlightでこの問題の一つの解決策は次のようにServiceKnownType上の既知の型を取得するためのメソッドを指定することでしたが:

[ServiceKnownType("GetKnownTypes", typeof(GetTypesHelper))] 

これは常に、.NETとSilverlightにも取り組んできましたが、 UWPやXamarinでは動作しません。私は今日これを試しました。これは私が得るエラーです:

System.InvalidOperationException:ServiceKnownTypeAttributeは存在しないAdapt.XivicClient.WCF.ServiceContracts.GetTypesHelper型のGetKnownTypesメソッドを指定します。メソッドは静的でなければならず、ICustomAttributeProvider型の1つのパラメータをとります。

もちろん、PCLおよび.NET標準ライブラリにはICustomAttributeProviderクラスがないため、これは実行できません。だから私はこの他の可能な解決策を試みた: https://stackoverflow.com/a/2104482/1878141

これは、サービスの動作を指定することによって動作します。しかし、再び、PCLとStandardにはIServiceBehaviorクラスがなく、どちらもAndroidとは言えません。

私はDataContractSerializerを置き換えることができると思ったのでこのコードを試しましたが、AndroidではNotImplementedExceptionを取得します。

 dataAccessServiceClient.Endpoint.EndpointBehaviors.Add(new XivicServicBehaviour()); 

public class XivicServicBehaviour : IEndpointBehavior 
{ 
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
    } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
    } 
} 

私たちのオプションは何ですか?

+0

RESTのAPIの設計への移行の選択肢が常にある:オペレーション)ここで

public class ServiceClientBase<T> : ClientBase<T>, IServiceClient, ICommunicationObject where T : class { #region Constructor public ServiceClientBase(Binding binding, EndpointAddress endpointAddress, sc.IKnownTypeGetter knownTypeGetter) : base(binding, endpointAddress) { foreach (var operation in Endpoint.Contract.Operations) { var knownTypes = knownTypeGetter.GetKnownTypes(); foreach (var type in knownTypes) { operation.KnownTypes.Add(type); } } } #endregion #region Open/Close public virtual Task OpenAsync() { var communicationObject = this as ICommunicationObject; return Task.Factory.FromAsync(communicationObject.BeginOpen(null, null), new Action<IAsyncResult>(communicationObject.EndOpen)); } public virtual Task CloseAsync() { var communicationObject = this as ICommunicationObject; return Task.Factory.FromAsync(communicationObject.BeginClose(null, null), new Action<IAsyncResult>(communicationObject.EndClose)); } #endregion } 

は別の味です。 WCF自体についても、既知の型は推奨されません。 –

+0

はい。私はここで私のチームでそれについて話していただけです。私はおそらく、長期的にはRESTにコードを移植することができますが、多くの呼び出しがあり、WCFが完全にうまく動作するときには、そのすべての問題に行くのはばかげているようです。私は知られているタイプがあまり推奨されていないと言ったときにあなたが何を意味するのか分かりません。既知の型はWCFのシリアル化の核心です。 –

答えて

0

私自身の質問に対する回答があります。それは長い間顔の中で私を見つめていて、とてもシンプルです。

私はなぜそれがわかりませんが、通常、既知の型を指定するためにOperationContractの引数を使用することをお勧めします。 8年间、これを唯一の方法と考えていました。 DataContractSerializerを使用して手動でシリアライズ/デシリアライズするときに既知の型を指定できることは常に知っていましたが、指定したDataContractSerializerをインスタンス化するWCFの既定の機能をオーバーライドする方法はわかりませんでした。

とにかく、別の方法があり、それは簡単ではありません。プロキシのコンストラクタに型のリストを取得するリストまたはインターフェイスを渡し、次にそのような型に操作を手動で追加します。

これは.NET標準プロキシのためのものです

public partial class WCFClientBase<T> : ClientBase<T> where T : class 
{ 
    public WCFClientBase(Binding binding, EndpointAddress endpointAddress, IKnownTypeGetter knownTypeGetter) : base(binding, endpointAddress) 
    { 
     foreach (var operation in Endpoint.Contract.Operations) 
     { 
      var knownTypes = knownTypeGetter.GetKnownTypes(); 

      foreach (var type in knownTypes) 
      { 
       operation.KnownTypes.Add(type); 
      } 
     } 
    } 
} 
関連する問題