Отражение: вызов метода получения производного свойства в базовом классе. - PullRequest
0 голосов
/ 04 сентября 2018

Я столкнулся с некоторыми проблемами при кодировании во время интеграции моего кода в большую систему. В следующем примере BaseClass и DerivedClass1 представляют собой ранее существующую большую систему, а DerivedClass2 - это мой код, который был унаследован от другого базового класса до слияния.

public abstract class BaseClass
{
    protected BaseClass()
    {
        foreach (var property in this.GetType().GetProperties())
        {
            var value = property.GetValue(this);
            if (value is PropertyEnvelop)
            {
                (...)
            }
        }
    }
}

public class DerivedClass1 : BaseClass
{
    public PropertyEnvelop MyProperty { get; }
        = new PropertyEnvelop("MyPropertyName", typeof(int), default(int));    
    // this is fine, because property initializers run in reverse order:
    // 1. Derived class property initializers
    // 2. Base class property initializers
    // 3. Base class constructor
    // 4. Derived class constructor
    // see link
}

public class DerivedClass2 : BaseClass
{
    public ComplexItem Item
        { get { return ComputeComplexItem(SimpleItem1, SimpleItem2); } }
    // this is BROKEN, because stuff like SimpleItem1, SimpleItem2
    // and ComputeComplexItem TOTALLY depend on some logic from
    // DerivedClass2 constructor and produce exceptions if the ctor
    // wasn't invoked yet.

    public DerivedClass2()
    {
        // prepare everything to bring DerivedClass2 in a valid state
    }
}

Ссылка

(Точнее говоря, BaseClass является реализацией INotifyPropertyChanged для MVVM, и он хочет выполнить некоторую автоподключение для своих свойств уведомлений.)

Вопрос в том, какая практика здесь плохая? 1) Вызов членов производного класса через отражение в базовом классе, или 2) Получатели свойств и методы, основанные на предположении, что конструктор их класса уже был вызван? Должен ли я добавить нулевые проверки и аналогичную логику во все мои свойства или я должен отключить это поведение базового класса (если я в любом случае не собираюсь использовать PropertyEnvelop где-нибудь в моем коде)? У меня есть сильное чувство, что неправильно пытаться вызывать методы получения свойств экземпляра, который еще не полностью создан (как говорится в второй части упомянутого блога), но есть ли официальные рекомендации, которые рекомендуют один вариант над другим? (У нас есть сложные классы ViewModel с большим количеством внутренней логики для выполнения во время ctors.)

К счастью для меня, настоящий BaseClass имеет флаг для отключения этого поведения, но он реализован как свойство виртуального bool, а унаследованные классы просто переопределяют его; поэтому BaseClass также вызывает своих виртуальных членов в своем конструкторе, что (AFAIK) также является плохой практикой кода.

1 Ответ

0 голосов
/ 07 сентября 2018

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

1) если вы пометите все свойства, которые вы хотите автоматически подключить в базовом конструкторе, с помощью некоторого [WarningAlertThisWillBeInvokedBeforeYourCtorAttribute], то, по крайней мере, у вас будет получатель и предупреждение в одном месте. В Reflection вы можете сначала проверить атрибуты и только после этого вызывать метод получения.

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

/// <summary>
/// WARNING! Property of this type should be initialized inline, not in ctor!
/// </summary>
public class PropertyEnvelop
{
    (...)
}

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

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