我们正在强制执行所有域对象以实现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要求的任何想法,但删除客户端上任何代码的要求(作为更新或部分类)?
答案 0 :(得分:3)
如果您确实要求WCF服务的所有C#使用者使用与原始代码相同的模型,请使用“添加服务引用”工具的“重用引用程序集中的类型”功能。确保将模型/合同/接口分解为单个程序集,其中没有其他实现代码作为共享的“定义”程序集。将此程序集标记为在“添加服务引用”工具生成客户端代理代码时重用类型的程序集。
此外,只是一个主动警告:通过为您的服务只有一个“官方”C#服务客户端实现来简化自己的事情。不要将Visual Studio生成的冗余服务引用代理添加到需要与服务连接的每个项目中。
修改强>
根据最近的个人经验,设计了一个模块化的,支持服务的API,允许我就模块化主题提供更多一般性建议,因为它不仅适用于WCF服务,还适用于总体设计。
在我们的系统中,我们完成了上面建议的创建单个“定义”程序集,其中只包含标记为[DataContract]
的对象:域对象,模型,数据契约,无论您希望将它们称为
在此程序集中,还是存储库接口的集合,它仅根据这些域对象定义方法。此程序集中还定义了强类型标识符结构,用于保存每个模型的标识值,因为这些模型是数据库持久化的,并且每个模型都有一个标识列。使用以这种方式包装int
的结构比使用int
本身更可取,因为现在我们得到了编译器辅助的语义分析,即Model1ID
不能转换为Model2ID
,因为它们语义上代表两个不同的域,尽管两个域都可以由int
类型表示。
模块化的驱动因素是这些存储库接口的定义。 WCF服务实现类简单地实现了所有必需的接口,类似于WCF服务客户端实现类,数据库存储库实现类,缓存代理实现类,方法调用日志记录实现类等。所有具体实现类都存在于其他程序集,即不在包含接口和模型的“定义”程序集中。这些类实现接口,并在消费者代码中显示为相同的。
关键是让您的API使用者代码与特定实现类无关,并且仅引用接口。模型本身保存为简单的数据容器,其中没有业务逻辑实现。我相信这种模式被称为贫血,但对我而言,“贫血”具有负面含义,因此我不喜欢在描述这种设计时使用该术语。
您得到的是实现业务逻辑的消费者代码,它不关心它是与WCF服务或直接与数据库通信,还是无缝地实现缓存,或者正在记录您的方法调用,或者其他什么您可以提出的其他代理用途。
总之,设计界面并让您的生活更轻松。但只有在你对自我克制的能力充满信心时才这样做。在我设计的系统中,我们有T4模板,它们生成几乎所有与WCF服务一起提供的样板代码,我们需要手动完成的任务是定义模型,设计接口和编写数据库访问代码。通过简单的右键单击和T4模板上的“运行自定义工具”,可以免费获得WCF外观。我喜欢它。 :)
答案 1 :(得分:0)
修复部分类的命名空间。您可能需要调整属性和继承。
namespace DCS2000.IDCardExclude.UI.IdCardManagerServiceReference
{
[Serializable]
[DataContract]
public partial class IdCard : DomainObject
{
public override int GetHashCode()
{
return EffDte.GetHashCode();
}
}
}