1

我们正在强制执行所有域对象来实现 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 的要求,但删除客户端上任何代码的要求(作为更新或作为部分类)的任何想法?

4

2 回答 2

3

如果您确实需要您的 WCF 服务的所有 C# 使用者使用与原始代码相同的模型,那么请使用“添加服务引用”工具的“在引用的程序集中重用类型”功能。确保将您的模型/合同/接口分解为单个程序集,其中没有其他实现代码用作共享的“定义”程序集。将此程序集标记为可在“添加服务引用”工具生成客户端代理代码时重用类型的程序集。

此外,只是一个主动警告:通过为您的服务仅使用一个“官方”C# 服务客户端实现来为您自己简化事情。不要将 Visual Studio 生成的冗余服务引用代理添加到需要与您的服务连接的每个项目中。

编辑:

从最近的个人经验来看,设计了一个模块化的、支持服务的 API,让我可以就模块化主题提供更一般的建议,因为它不仅涉及 WCF 服务,还涉及总体设计。

在我们的系统中,我们已经按照我上面的建议创建了一个“定义”程序集,该程序集仅包含标记为的对象[DataContract]:域对象、模型、数据契约,无论您喜欢将它们称为什么。

在这个程序集中也是一个存储库接口的集合,它仅根据这些域对象定义方法。该程序集中还定义了强类型标识符结构,用于保存每个模型的标识值,因为这些模型是数据库持久化的,并且每个模型都有一个标识列。使用以这种方式包装ints 的结构比使用int自身更可取,因为现在我们得到了编译器辅助的语义分析,即Model1ID不可转换为,Model2ID因为它们在语义上表示两个不同的域,尽管这两个域都可以由int类型表示。

推动模块化的是这些存储库接口的定义。WCF 服务实现类简单地实现了所有需要的接口,与 WCF 服务客户端实现类、数据库存储库实现类、缓存代理实现类、方法调用日志实现类等类似。所有具体实现类都存在于其他程序集,即不在包含接口和模型的“定义”程序集中。这些类实现了接口并且在消费者代码中看起来是一样的。

关键是让您的 API 使用者代码与特定的实现类无关,并且只引用接口。模型本身被保存为简单的数据容器,其中没有业务逻辑实现。我相信这种模式被称为贫血,但对我来说,“贫血”有负面含义,所以我不喜欢在描述这种设计时使用这个词。

你得到的是实现业务逻辑的消费者代码,它不关心它是与 WCF 服务还是直接与数据库通信,或者缓存正在无缝实现,或者你的方法调用正在被记录,或者任何其他代理使用你可以想出。

In summary, design with interfaces and make your life easier for yourself. But only do this if you are confident in your ability to practice self-restraint. In our system which I designed, we have T4 templates which generate almost all of the boilerplate code that comes along with WCF services to the point where all we have to do manually is define the model, design the interface, and write the database access code. The WCF facade comes free with a simple right-click and "Run Custom Tool" on the T4 templates. I love it. :)

于 2010-10-08T14:45:01.323 回答
0

修复部分类上的命名空间。您可能需要调整属性和继承。

namespace DCS2000.IDCardExclude.UI.IdCardManagerServiceReference
{
  [Serializable]
  [DataContract]
  public partial class IdCard : DomainObject
  {
    public override int GetHashCode()
    {
        return EffDte.GetHashCode();
    }
  }
}
于 2010-10-06T15:00:52.050 回答