Перевод одного объекта в другой с помощью метода расширения - поиск альтернативных решений - PullRequest
1 голос
/ 15 августа 2011

Это может быть немного странным вопросом, и то, что у меня сейчас есть, работает, но мне кажется немного странным, и мне интересно, что это из-за плохого дизайна / архитектуры. Любые мысли здесь будут оценены.

Первоначальный дизайн в кодовой базе, которую я унаследовал от кого-то другого. У нас есть класс linq-to-sql (автоматически генерируется в файле конструктора dbml).


[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.ARCustomers")]
public partial class ARCustomer : INotifyPropertyChanging, INotifyPropertyChanged
{
    // variables
    // extensibility method defs
    // ctor
    // properties
    // etc.
}

Затем другой класс класса с именем ArCustomer (обратите внимание на строчную букву "r"), который является расширенной версией автоматически сгенерированного класса. Когда я говорю «расширенный», я имею в виду, что у него есть все свойства класса LINQ, плюс еще несколько, которые требуют некоторой логики для заполнения.

В коде есть много мест, где мы хотим взять ARCustomer и превратить его в ArCustomer. Поэтому я написал метод расширения (это то, что мне показалось странным) для класса ArCustomer.


public static ArCustomer FromDatacontextObject(this ArCustomer customer, ARCustomer datacontextObject)
{
    var arCustomer = new ArCustomer();
    arCustomer.Id = datacontextObject.ProjectID;
    // more of the same

    // now populate the other fields that don't exist on the datacontextObject

    return arCustomer;
}

Это называется так.


var customerfromDb = accountReceivableRepository.GetCurCustomer(arId);
ArCustomer customer = new ArCustomer();
customer = customer.FromDatacontextObject(customerfromDb);

Мне кажется, что это неправильно, но я не знаю ни одной лучшей альтернативы в моей голове. (Будет ли работать неполный класс, содержащий расширенные свойства? Заполните их в своем конструкторе?) Или, может быть, все в порядке ... Меня интересуют несколько вещей ...

  1. Правильно ли я чувствую, что это неправильно / странно / плохо?
  2. В частности, какие минусы можно найти в реализованном мною решении? Мне кажется, что я слишком часто чешу голову, пытаясь разграничить два класса и понять, что есть что.
  3. Есть ли у них плюсы?
  4. Есть ли лучшие решения (и почему они лучше)?

(Несвязанный - я надеюсь, что такой вопрос подходит для переполнения стека. Я почти чувствую, что прошу мини-обзор кода, который может быть субъективным; с другой стороны, я попытался задать некоторые конкретные вопросы и Я чувствую, что не должен быть единственным разработчиком, столкнувшимся с такой ситуацией («У меня есть один объект, и мне нужно превратить его в другой»), так что, надеюсь, есть что-то, что можно получить, если оставить поток открытым).

Спасибо, ребята!

Ответы [ 3 ]

2 голосов
/ 15 августа 2011

Ваши инстинкты служат вам хорошо.

Наличие двух классов с одинаковыми именами (различаются только в случае) технически разрешено компилятором C #, но это плохая идея.Кроме того, он не совместим с CLS.

Это плохая идея по той причине, которую вы уже указали: читаемость .Не стоит недооценивать важность читабельности.Лично это мой номер один показатель качества кода.Читаемый код имеет тенденцию иметь меньше ошибок, и его легче отлаживать / поддерживать.

Классы, сгенерированные LINQ to SQL, уже являются частичными классами.Вы можете добавить отдельный файл кода, чтобы определить любые дополнительные детали, которые вы хотите.И это предпочтительный метод для выполнения того, что вы описываете.Его проще поддерживать и понимать.

В качестве альтернативы вы можете создать класс ViewModel, содержащий ARCustomer.(Это зависит от вашей архитектуры).

2 голосов
/ 15 августа 2011

Если вы измените метод расширения для расширения объекта базы данных, у вас будет более естественный API IMO

public static ArCustomer ToDomainObject(this ARCustomer datacontextObject)
{
   var arCustomer = new ArCustomer();
   arCustomer.Id = datacontextObject.ProjectID;
   // more of the same

   // now populate the other fields that don't exist on the datacontextObject

   return arCustomer;
}

, тогда код доступа к данным будет выглядеть следующим образом

var customerfromDb = accountReceivableRepository.GetCurCustomer(arId);
ArCustomer customer = customerfromDb.ToDomainObject();
0 голосов
/ 15 августа 2011

Несколько дней назад у меня была такая же проблема. И я нашел некоторые обсуждения на эту тему. Эти темы могут помочь: Тема 1 , Тема 2

Как я понял, нет лучшего способа сделать то, что вы делаете. Однако вы можете попытаться использовать отражение, чтобы перебрать все поля в родительском объекте, чтобы скопировать их в соответствующие поля в дочернем объекте. Пример кода здесь , И обсуждение здесь .

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

...