Как мне применить «шаблон» или «скелет» кода в C # здесь? - PullRequest
2 голосов
/ 26 февраля 2010

На моем бизнес-уровне мне нужно много, много методов, которые следуют шаблону:

public BusinessClass PropertyName
{
    get
    {
        if (this.m_LocallyCachedValue == null)
        {
            if (this.Record == null)
            {
                this.m_LocallyCachedValue = new BusinessClass(
                     this.Database, this.PropertyId);
            }
            else
            {
                this.m_LocallyCachedValue = new BusinessClass(
                     this.Database, this.Record.ForeignKeyName);
            }
        }
        return this.m_LocallyCachedValue;
    }
}

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

BusinessClass - это имя типа, которое необходимо заменить, а PropertyName, PropertyId, ForeignKeyName и m_LocallyCachedValue - все переменные, которые должны быть заменены.

Здесь можно использовать атрибуты? Мне нужно отражение? Как мне написать предоставленный мною скелет в одном месте, а затем просто написать строку или два, содержащие параметры подстановки, и заставить шаблон распространяться сам?

РЕДАКТИРОВАТЬ: изменил мой вводящий в заблуждение заголовок - я надеюсь найти решение, которое не включает в себя методы генерации кода или копирования / вставки, а скорее, чтобы иметь возможность написать скелет кода в базовом классе в некоторых сформировать и сделать так, чтобы он был "реализован" в виде множества подклассов как средство доступа к различным свойствам.

РЕДАКТИРОВАТЬ: Вот мое решение, как предложено, но оставлено невыполненным выбранным ответчиком.

// I'll write many of these...
public BusinessClass PropertyName
{
    get
    {
        return GetSingleRelation(ref this.m_LocallyCachedValue, 
            this.PropertyId, "ForeignKeyName");
    }
}

// That all call this.
public TBusinessClass GetSingleRelation<TBusinessClass>(
    ref TBusinessClass cachedField, int fieldId, string contextFieldName)
{
    if (cachedField == null)
    {
        if (this.Record == null)
        {
            ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
                new Type[] { this.Database.GetType(), typeof(int) });
            cachedField = (TBusinessClass)ci.Invoke(
                new object[] { this.Database, fieldId });
        }
        else
        {
            var obj = this.Record.GetType().GetProperty(objName).GetValue(
                this.Record, null);
            ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
                new Type[] { this.Database.GetType(), obj.GetType()});
            cachedField = (TBusinessClass)ci.Invoke(
                new object[] { this.Database, obj });
        }
    }

    return cachedField;
}

Ответы [ 3 ]

1 голос
/ 26 февраля 2010

Вы можете проверить, используя шаблоны T4. Я не совсем уверен, что является «ресурсом» для T4, но я нашел хорошую статью об этом в VisualStudioMagazine.

Он бесплатный, имеет простой в использовании синтаксис и фактически используется многими проектами (например, Subsonic) для генерации кода, поэтому вы должны быть в состоянии найти некоторые реальные сценарии.

1 голос
/ 26 февраля 2010

Выезд CodeSmith . У них есть бесплатная пробная версия, и это не слишком дорого, если вы хотите приобрести его. Я использовал его, и он отлично подходит для генерации кода, основанного на базах данных (что, по-моему, вы делаете) После того, как вы настроили шаблон, вы можете в любой момент восстановить код. Вы можете сделать так, чтобы он считывал имена свойств прямо из схемы базы данных, или вы можете ввести значения, которые вы хотите использовать. Я уверен, что вы могли бы даже заставить его читать значения из файла, если вы хотите создать целую группу классов одновременно.

0 голосов
/ 26 февраля 2010

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

Или вы можете превратить эту функцию в базовый класс или вспомогательный метод.

public BusinessClass MyProperty
{
    get { return GetCached("MyProperty", "PropertyId", "FKName", "LocalValue"); }
}

Я оставлю тело GetCached() на ваше усмотрение, но оно в основном совпадает с тем, что вы опубликовали с переменными, переданными в качестве аргументов.

Если какое-либо из этих значений одинаково для всех свойств в классе, вы, конечно, можете извлечь их из переменных экземпляра и передать только GetCached () те вещи, которые зависят от каждого свойства.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...