WCFの抽象メソッドサーバー側を維持する方法
-
28-09-2019 - |
質問
GethashCodeを実装するために、すべてのドメインオブジェクトを実施しています。
namespace Core
{
[Serializable]
public abstract class DomainObject
{
public abstract override int GetHashCode();
}
}
namespace Entity.Domain
{
[Serializable]
[DataContract]
public partial class IdCard : DomainObject
{
private System.Int32 _effDte;
[DataMember]
public virtual System.Int32 EffDte
{
get { return _effDte; }
set { _effDte = value; }
}
public override int GetHashCode()
{
return EffDte.GetHashCode();
}
}
}
これらのドメインオブジェクトをWCFを介して公開する場合、次の生成されたサービスでは、コンパイルするためにポストアップデートの変更が必要です。
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3053
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace IdCardManagerServiceReference {
using System.Runtime.Serialization;
using System;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="IdCard", Namespace="http://schemas.datacontract.org/2004/07/Entity.Domain")]
[System.SerializableAttribute()]
public partial class IdCard : Core.DomainObject, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private int EffDteField;
[global::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
get {
return this.extensionDataField;
}
set {
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public int EffDte {
get {
return this.EffDteField;
}
set {
if ((this.EffDteField.Equals(value) != true)) {
this.EffDteField = value;
this.RaisePropertyChanged("EffDte");
}
}
}
}
GethashCodeの要件を維持する方法に関するアイデアはありますが、クライアントのコードの要件を削除します(更新または部分クラスとして)?
解決
WCFサービスのすべてのC#消費者が実際に同じモデルを使用して、元のコードを使用して同じモデルを使用することが本当に必要な場合は、参照アセンブリの「追加」ツールの「再利用タイプ」機能を使用します。モデル /契約 /インターフェイスを、共有「定義」アセンブリとして機能する他の実装コードが含まれていない単一のアセンブリに分割してください。このアセンブリを、「サービスリファレンスの追加」ツールがクライアントプロキシコードを生成するときからタイプを再利用するものとしてマークします。
また、積極的な警告:サービスの「公式」C#サービスクライアントの実装を1つだけ持っていることで、自分のために物事を簡素化します。 Visual Studioによって生成された冗長なサービスリファレンスプロキシをすべてのプロジェクトに追加しないでください。これには、サービスとの接続が必要です。
編集:
最近の個人的な経験から言えば、モジュール式のサービス対応APIを設計したことで、WCFサービスだけでなく包括的なデザインに関連するモジュール性のトピックに関するより一般的なアドバイスを提供することができます。
私たちのシステムでは、としてマークされたオブジェクトのみを含む単一の「定義」アセンブリを作成する際に、上記で提案したことを実行しました [DataContract]
: :ドメインオブジェクト、モデル、データ契約、あなたがそれらをどのように参照したいか。
このアセンブリには、これらのドメインオブジェクトのみでメソッドを定義するリポジトリインターフェイスのコレクションもあります。また、このアセンブリで定義された強力な型識別子構造物もあります。これらのモデルはデータベースが持続し、それぞれがID列を持っているため、各モデルごとにアイデンティティ値を保持するために使用されます。ラップする構造体を使用します int
この方法では、使用する方が望ましいです int
今からそれ自体がコンパイラーアシストされたセマンティック分析を取得します。 Model1ID
に変換できません Model2ID
両方のドメインが表現できるという事実にもかかわらず、それらは2つの異なるドメインを意味的に表しているため int
タイプ。
モジュール性を促進するのは、これらのリポジトリインターフェイスの定義です。 WCFサービス実装クラスは、WCFサービスクライアント実装クラス、データベースリポジトリ実装クラス、キャッシュプロキシ実装クラス、メソッドリビューロギング実装クラスなどと同様に、必要なすべてのインターフェイスを単純に実装します。すべての具体的な実装クラスが存在します。他のアセンブリ、つまり、インターフェイスとモデルを含む「定義」アセンブリにはありません。これらのクラスはインターフェイスを実装し、消費者コードに同じように表示されます。
重要なのは、API消費者コードを特定の実装クラスの不可知論者に保ち、インターフェイスのみを参照することです。モデル自体は、ビジネスロジックの実装が見つからない単純なデータコンテナとして保持されています。このパターンは貧血と呼ばれていると思いますが、私にとっては「貧血」には否定的な意味合いがあるので、このデザインを説明する際にその用語を使用するのは好きではありません。
あなたが得るのは、WCFサービスと直接データベースに通信しているか、キャッシュがシームレスに実装されているか、メソッドの呼び出しがログに記録されているか、他のプロキシ使用が使用されているかどうかを気にしないビジネスロジックを実装する消費者コードですあなたは思いつくことができます。
要約すると、インターフェイスを使用してデザインし、自分の生活を楽にします。しかし、自己抑制を実践する能力に自信がある場合にのみこれを行います。私が設計したシステムには、WCFサービスと一緒に付属するほぼすべてのボイラープレートコードを生成するT4テンプレートがあり、手動で行う必要があるすべてのポイントがモデルを定義し、インターフェイスを設計し、データベースアクセスコードを書き込むことです。 。 WCFファサードには、T4テンプレートにシンプルな右クリックと「カスタムツールを実行」して無料で提供されます。大好きです。 :)
他のヒント
部分クラスの名前空間を修正します。属性と継承を調整する必要があるかもしれません。
namespace DCS2000.IDCardExclude.UI.IdCardManagerServiceReference
{
[Serializable]
[DataContract]
public partial class IdCard : DomainObject
{
public override int GetHashCode()
{
return EffDte.GetHashCode();
}
}
}