Какой самый эффективный способ внедрить поведение во все мои объекты?

#c# #entity-framework-4 #extension-methods

#c# #entity-framework-4 #расширение-методы

Вопрос:

Я конвертирую модель больших данных из старой библиотеки Microsoft data access в Entity Framework 4. Я хотел бы «внедрить» эти два метода в большинство, если не во все, объектов, которые были сгенерированы из существующей базы данных в моей модели EF:

     public bool Deleted
    {
        get { return this.EntityState == System.Data.EntityState.Deleted; }
        set 
        {
            if (value)
                Context.DeleteObject(this);
        }
    }

    public bool Inserted
    {
        get { return this.EntityState == System.Data.EntityState.Added; }
        set
        {
            if (value)
                Context.AddObject(this.GetType().Name, this);
        }
    }
  

Вместо того, чтобы создавать частичный класс для каждого объекта (их более 100), какой лучший способ добавить эти методы ко всем объектам в модели?

Заранее спасибо за ваши предложения.

Комментарии:

1. добавить в базовый класс common entity?

2. @Mitch, спасибо за предложение. Я уже пытался добавить частичный класс для EntityObject, но, очевидно, EntityObject не видит свойство EntityState.

Ответ №1:

Я бы изменил шаблон EF T4, чтобы автоматически генерировать эти свойства.

Ответ №2:

Расширяя ответ @Daz (несколько скудный): щелкните правой кнопкой мыши в конструкторе и выберите Add Code Generation Item... , затем ADO.NET Entity Object Generator. будет создан шаблон, который генерирует точно такой же код, который уже создан компилятором, который затем вы можете настроить. Откройте его, довольно легко увидеть, как его изменить. Он разработан именно для той цели, которую вы описываете.

Вот недавняя статья MSDN, в которой все подробно описано.

Комментарии:

1. @Daz, спасибо за предложение. Я надеялся сделать это вне генератора кода. Я думал, что можно было бы разработать метод аспекта или расширения, чтобы добавить это поведение к классам. Но я могу изменить код gen, если не представлено другого решения.

Ответ №3:

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

Комментарии:

1. Питер прав. Я хочу, чтобы это поведение было вне генерации кода, или хочу изменить генерацию кода, чтобы иметь эти свойства.

Ответ №4:

Методы расширения делают свое дело. Но, конечно, это методы, а не надлежащие свойства, которые вы создаете в своем примере (свойства расширения еще не существуют во фреймворке, только методы расширения).

 public static class EntityObjectExtensions
{
    public static bool IsDeleted(this EntityObject obj)
    {
        return obj.EntityState == System.Data.EntityState.Deleted;
    }

    public static bool Delete(this EntityObject obj)
    {
        Context.DeleteObject(obj);
    }

    public static bool IsInserted(this EntityObject obj)
    {
        return obj.EntityState == System.Data.EntityState.Added;
    }

    public static bool Insert(this EntityObject obj)
    {
        Context.AddObject(obj.GetType().Name, obj);
    }
}
  

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

Комментарии:

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

2. @John Это было именно то, что я понял из вашего вопроса. Разве мой ответ не удовлетворяет этому требованию?

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

4. Хорошо, я понял. К сожалению, не существует тысяч вариантов. Либо вы вносите 1000 изменений в 1000 классах, либо вносите 1 изменение в хорошо выбранном месте. Зная это … 1 / Вы можете оставить вызовы без изменений при условии, что вы добавляете свойства путем генерации кода, но вы не хотите. 2 / расширениями могут быть только методы: это заставляет изменять все вызовы, а вы не хотите. 3/ Свойства могут быть добавлены к общему классу-предку: вы пытались добавить частичный класс к EntityObject, но, похоже, вам это не удалось. Ошибка… похоже, что, возможно, придется рассмотреть компромисс…

5. Ситра, я ценю твои усилия. Безусловно, есть другие способы сделать это, и все они в дальнейшем вызовут проблемы по мере обновления EF или его шаблона, или если мы внедрим DevForce, или модель обновится, или приложение эволюционирует. Оказалось, что не всем объектам нужны эти свойства, поэтому мы просто создали те, которые нам были нужны. Кроме того, ваш приведенный выше пример не будет работать во время выполнения. Например, множественность коллекции вызовет контекст. Сбой AddObject(obj.GetType().Name, obj), поэтому он не может быть универсальным таким образом.