Способы сохранения абстрактного метода на стороне сервера для WCF - PullRequest
1 голос
/ 06 октября 2010

Мы применяем все наши доменные объекты для реализации 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, но отменить требование для любого кода на клиенте (как обновление или как частичные классы)?

Ответы [ 2 ]

3 голосов
/ 08 октября 2010

Если вам действительно требуется, чтобы все потребители C # вашей службы WCF использовали одни и те же модели с оригинальным кодом в действии, тогда используйте функцию «Добавить ссылку на службу» «Повторное использование типов в ссылочных сборках». Обязательно разбивайте свои модели / контракты / интерфейсы на одну сборку без какого-либо другого кода реализации, который бы служил общей сборкой «определения». Отметьте эту сборку как ту, для которой можно повторно использовать типы, когда инструмент «Добавить ссылку на службу» создает код прокси-клиента клиента.

Кроме того, просто предупреждающее предупреждение: упростите себе задачу, имея только одну "официальную" реализацию клиента службы C # для вашей службы. Не добавляйте избыточные ссылки на службы, сгенерированные Visual Studio, в каждый проект, для которого требуется подключение к вашей службе.

EDIT:

Исходя из недавнего личного опыта, разработав модульный API с поддержкой сервисов, я могу дать более общие рекомендации по модульности, поскольку это касается не только сервисов WCF, но и всеобъемлющего дизайна.

В нашей системе мы сделали то, что я предложил выше, создав единую сборку «Определение», которая содержит только объекты, помеченные как [DataContract]: доменные объекты, модели, контракты данных, что бы вы ни называли.

В этой сборке также представлена ​​коллекция интерфейсов репозитория, которая определяет методы исключительно в терминах этих доменных объектов. Существуют также строго идентифицированные структуры идентификаторов, определенные в этой сборке, которые используются для хранения значений идентификаторов для каждой модели, поскольку эти модели сохраняются в базе данных и у каждой есть столбец идентификаторов. Использование структур, которые обертывают int s таким способом, предпочтительнее, чем использование самого int, поскольку теперь мы получаем семантический анализ с помощью компилятора, то есть Model1ID не может быть преобразован в Model2ID, поскольку они семантически представляют две разные области, несмотря на тот факт, что что оба домена представимы типом int.

Что определяет модульность, так это определение этих интерфейсов репозитория. Класс реализации службы WCF просто реализует все необходимые интерфейсы, аналогично классу реализации клиента службы WCF, классу реализации репозитория базы данных, классу реализации прокси-сервера кэширования, классу реализации ведения журнала вызовов методов и т. Д. Все конкретные классы реализации существуют в другие сборки, т.е. не в сборке «Определение», которая содержит интерфейсы и модели. Эти классы реализуют интерфейсы и представляются потребительскому коду одинаковыми.

Ключ заключается в том, чтобы ваш потребительский код API не зависел от конкретных классов реализации и ссылался только на интерфейсы. Сами модели хранятся в виде простых контейнеров данных, в которых отсутствует реализация бизнес-логики. Я полагаю, что этот паттерн называется анемичным, но для меня «анемичный» имеет негативную коннотацию, поэтому я не люблю использовать этот термин при описании этого дизайна.

То, что вы получаете, - это потребительский код, реализующий бизнес-логику, которой не важно, взаимодействует ли он со службой WCF или напрямую с базой данных, или что кеширование реализовано незаметно, или что ваши вызовы методов регистрируются, или что-то еще другие варианты использования прокси, которые вы можете придумать.

В итоге, создавайте интерфейсы и сделайте свою жизнь проще для себя. Но делайте это только в том случае, если вы уверены в своей способности сдерживать себя. В нашей системе, которую я разработал, у нас есть шаблоны T4, которые генерируют почти весь шаблонный код, который поставляется вместе со службами WCF, и все, что нам нужно сделать вручную, - это определить модель, спроектировать интерфейс и написать код доступа к базе данных. , Фасад WCF предоставляется бесплатно с помощью простого щелчка правой кнопкой мыши и запуска «Запустить пользовательский инструмент» в шаблонах T4. Я люблю это. :)

0 голосов
/ 06 октября 2010

Исправьте пространство имен в вашем частичном классе.Возможно, вам придется настроить атрибуты и наследование.

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