C# 为WCF保留抽象方法服务器端的方法

C# 为WCF保留抽象方法服务器端的方法,c#,wcf,gethashcode,abstract-methods,C#,Wcf,Gethashcode,Abstract Methods,我们正在强制所有域对象来实现GetHashCode namespace Core { [Serializable] public abstract class DomainObject { public abstract override int GetHashCode(); } } namespace Entity.Domain { [Serializable] [DataContract] public partial class IdCard : Do

我们正在强制所有域对象来实现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");
            }
        }
    }
}
//------------------------------------------------------------------------------
// 
//这段代码是由一个工具生成的。
//运行时版本:2.0.50727.3053
//
//对此文件的更改可能会导致不正确的行为,如果
//重新生成代码。
// 
//------------------------------------------------------------------------------
命名空间IdCardManagerServiceReference{
使用System.Runtime.Serialization;
使用制度;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute(“System.Runtime.Serialization”,“3.0.0.0”)]
[System.Runtime.Serialization.DataContractAttribute(Name=“IdCard”,命名空间=”http://schemas.datacontract.org/2004/07/Entity.Domain")]
[System.SerializableAttribute()]
公共部分类IdCard:Core.DomainObject、System.Runtime.Serialization.IEExtensibleDataObject、System.ComponentModel.INotifyPropertyChanged{
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
私人内场;
[全局::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData{
得到{
返回此.extensionDataField;
}
设置{
this.extensionDataField=值;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
公共效率{
得到{
返回此.EffDteField;
}
设置{
if((this.EffDteField.Equals(value)!=true)){
this.EffDteField=值;
本.提高产权变更(“生效”);
}
}
}
}

关于如何保留对GetHashCode的要求,但删除对客户端上任何代码的要求(作为更新或部分类)的任何想法?修复部分类上的命名空间。您可能需要调整属性和继承

namespace DCS2000.IDCardExclude.UI.IdCardManagerServiceReference
{
  [Serializable]
  [DataContract]
  public partial class IdCard : DomainObject
  {
    public override int GetHashCode()
    {
        return EffDte.GetHashCode();
    }
  }
}

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

另外,只是一个主动警告:只为您的服务提供一个“官方”C#服务客户端实现,从而简化您的工作。不要将Visual Studio生成的冗余服务引用代理添加到每个需要与您的服务连接的项目中

编辑:

根据最近的个人经验,在设计了一个模块化的、支持服务的API之后,请允许我就模块化主题提供更多的一般性建议,因为它不仅涉及WCF服务,而且涉及总体设计

在我们的系统中,我们按照我上面的建议创建了一个“定义”程序集,该程序集只包含标记为
[DataContract]
的对象:域对象、模型、数据契约,以及您喜欢将其称为的任何对象

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

驱动模块化的是这些存储库接口的定义。WCF服务实现类仅实现所有必需的接口,与WCF服务客户端实现类、数据库存储库实现类、缓存代理实现类、方法调用日志实现类似所有具体实现类都存在于其他程序集中,即不存在于包含接口和模型的“定义”程序集中。这些类实现接口,并在使用者代码中显示为相同

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

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

总之,使用界面进行设计,让您的生活更轻松。但只有在您对自己的自我约束能力有信心的情况下,才可以这样做。在我设计的系统中,我们有T4模板,它生成了WCF服务附带的几乎所有样板代码,我们需要手动执行的所有操作都是de细化模型,设计界面,以及