c# - 反射:在基类中调用派生属性 getter

标签 c# mvvm reflection conventions

在将代码集成到更大的系统中时,我遇到了一些代码约定问题。在下面的示例中,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
    }
}

Link

(更具体地说,BaseClass 是 MVVM 的 INotifyPropertyChanged 的​​实现,它希望对其通知属性进行一些自动连接。)

问题是,这里的什么做法是不好的? 1) 通过基类中的反射调用派生类成员,或者 2) 依赖于其类的构造函数已被调用的假设的属性 getter 和方法?我应该在我的所有属性中添加空检查和类似的逻辑,还是应该禁用这个基类行为(如果我无论如何都不打算在我的代码中的任何地方使用 PropertyEnvelop)?我有一种强烈的感觉,尝试调用尚未完全实例化的实例的属性的 getter 是错误的(正如上述博客的 second part 所说),但是是否有任何官方指南推荐一个选项而不是另一个选项? (我们有复杂的 ViewModel 类,其中有很多内部逻辑要在 ctor 期间运行。)

对我来说幸运的是,真正的 BaseClass 有一个标志来禁用此行为,但它是作为虚拟 bool 属性实现的,继承的类只是覆盖它;因此,BaseClass 还在其构造函数中调用其虚拟成员,这(AFAIK)也是一种不好的代码实践。

最佳答案

我公司最后决定他们原来的模式是错误的,他们将改 rebase 类的实现。建议是:

1) 如果你用一些 [WarningAlertThisWillBeInvokedBeforeYourCtorAttribute] 标记你想在基础构造函数中自动 Hook 的所有属性,那么你至少会在一个地方拥有 getter 和警告。在反射中,您可以首先检查属性,然后才调用 getter。

2)如果你不想引入属性(在这种情况下,引入了自动钩子(Hook)以尽可能地加快开发),你至少可以在调用getter之前检查属性的类型。然后您可以将警告放入类型摘要中,例如

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

3) 通常,在基类ctor 中调用属性getter 根本不是一个好主意,所以我们将寻求另一种解决方案。

关于c# - 反射:在基类中调用派生属性 getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52166638/

相关文章:

c# - 引用其他函数 C# 创建的实例的函数

c# - 如何使用 MVVM Light ViewModelLocator 处理多个 ViewModel

java - 使用 Field.set 设置 GameProfile(更改玩家的名字)

java - Class.getFields() 返回的字段顺序

c# - 在ms visual studio中使用是否必须单独安装ms sql server 2005

c# - 网络应用程序上的计时器

c# - CartesianChart(实时图表)不适用于 DataTemplate

haskell - 如何用 'reflection' 包替换 ImplicitParams?

c# - 如何从 T-SQL 转换 Sum over partition

c# - Unity-Container 在什么时间点在 WPF 应用程序中处理它的对象?