Шаблон проектирования для добавления атрибутов в базовый класс - PullRequest
0 голосов
/ 26 ноября 2009

Я уверен, что есть умный способ справиться с этим, но я просто не могу понять это прямо в моей голове. Вот сценарий:

У меня есть базовый класс с около 30 свойствами. Скажите, что у меня есть свойство в этом классе с именем Type. Для подмножества экземпляров этого класса я хочу добавить еще несколько свойств на основе свойства Type. В этом случае, когда я создаю объекты, я могу просто создать подкласс базы, который содержит эти дополнительные свойства. Моя проблема в том, что пользователь может изменить тип на основе поля со списком, и мне нужно иметь возможность либо привести его обратно к базовому классу, либо изменить его на совершенно другой подкласс с другим подмножеством дополнительных свойств. Надеюсь, это ясно видно. Любые рекомендации о том, как справиться с этим?

Примечание: это приложение в коричневом поле, поэтому, хотя идея пакета свойств привлекательна, она также невозможна без серьезной боли.

Ответы [ 5 ]

2 голосов
/ 26 ноября 2009

Вы можете сделать это, если начнете с очень измененного фабричного образца .

Я бы создал базовый класс, и всякий раз, когда свойство Type изменяется в результате ввода пользователя, класс factory-ish (я назову его Бобом) отвечает за возвращение класса указанного типа. Вы бы позвонили Бобу, передав тип и текущий объект, и Боб вернул бы определенный подтип.

Например:

public class MyBase
{
    public string Type { get; set; }
    public string CommonProperty { get; set; }
}

public class ExtendedClass : MyBase
{
    public string ExtraProperty { get; set; }
}

public static class MyNotFactory
{
    public static MyBase Create(MyBase baseObject)
    {
        switch (baseObject.Type)
        {
            case "Extended":
                return baseObject as ExtendedClass;
                break;
            default:
                return baseObject;
                break;
        }
    }
}

(Примечание: я не проверял код)

Редактировать: Знаете ... сейчас это не совсем заводской шаблон, я поместил его в код ... Я переименовал материал.

2 голосов
/ 26 ноября 2009

Просто есть список свойств ...

List<Properties> MyProps;

И добавить к нему соответственно.

1 голос
/ 26 ноября 2009

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

Я бы создал иерархию наследования по своему усмотрению, используя обычное наследование, а затем заглянул в Activator.CreateInstance (или статический метод фабрики в базовом классе) для создания экземпляров объектов.

0 голосов
/ 26 ноября 2009

Спасибо всем за ваши ответы. В конце концов я нашел этот пост: «Использование отражения для копирования свойств базового класса»

Я немного адаптировал этот пост и закончил тем, что это мое рабочее решение. (в моем примере я создал класс Base и получил несколько классов, производных от него):

  Private Shared Sub CopyBaseProperties(ByVal pSource As Base, ByVal pDestination As Base)

      Dim fields() As FieldInfo = GetType(Base).GetFields(BindingFlags.NonPublic Or BindingFlags.Public Or BindingFlags.Instance)
      For Each tmpField As FieldInfo In fields
         tmpField.SetValue(pDestination, tmpField.GetValue(pSource))
      Next

   End Sub
0 голосов
/ 26 ноября 2009

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

Единственный способ «изменить типы» - назначить другой экземпляр совместимого типа переменной (если переменная будет принимать типы, реализующие Foo, и типы Foo1 и Foo2, оба реализуют / расширяют Foo, тогда экземпляр любого из них может быть назначен переменной

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

Ваш вопрос звучит подозрительно, как если бы вы хотели иметь следующее:

class FooWithAdOns
{
    int Blah { get; set;}
    int Wibble { get; set }
    Type AddOn { get; set; }
    /* if AddOn type is AddOnX */
    int X { get; set; }
    /* if AddOn type is AddOnY */
    int Y { get; set; }
}

class AddOnX
{
    int X { get; set;}
}


class AddOnY
{
    int Y { get; set;}
}

Было ли существование X / Y на FooWithAddOn динамическим.

Есть два способа достичь этого, один возможный сейчас, но ограниченный взаимодействиями пользовательского интерфейса, основанными на отражении, с использованием таких вещей, как ITypedList . Другой гораздо более мощный, но основан на функции динамической диспетчеризации c # 4.0, где имена методов / свойств вырабатываются во время выполнения.

Если вы просто взаимодействуете с пользовательским интерфейсом через что-то вроде PropertyGrid, тогда первый подход будет работать до тех пор, пока каждый раз, когда вы изменяете «список» свойств, вы перестраиваете сетку свойств, последний будет отлично работать в коде, но, для кода пользовательского интерфейса вам нужно написать оболочку, способную выполнять большую часть того, что делает ITypedList, чтобы предоставить текущие «поддельные свойства» отражающему пользовательскому интерфейсу.

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