【发布时间】:2011-05-11 19:49:09
【问题描述】:
我有几个类构成了一个过于复杂的对象图。这是一个较小的场景。假设 INotifyPropertyChanged 已就位。
class A
{
public InternalType InterestingProperty { get; set; }
}
class B
{
public A Component { get; set; }
}
我的助手类监视这些事件并在对象的属性发生变化时更新其属性。这样做是为了让其他一些对尽可能多的对象的十几个属性感兴趣的其他类很容易访问。这一切都打包在一个具有多个变体的框架中,因此继承在起作用。
我已经完成了第一个场景,最后得到了一个像这样的具体类:
class ScenarioOnePropertySpy
{
protected ScenarioOne PropertySpy(Foo thingToMonitor)
{
_thingToMonitor = thingToMonitor;
RegisterForEvents()
}
public B InterestingB { get; }
protected RegisterForEvents()
{
// * Register for _thingToMonitor propertyChanged if first time.
// * If B is different, unregister the old and register the new.
// * If B hasn't been set yet register for PropertyChanged on it.
// * If B.Component isn't the same as last time unregister the
// old and register the new.
}
protected Update()
{
// Some monitored object changed; refresh property values and
// update events in case some monitored object was replaced.
B = _thingToMonitor.B;
RegisterForEvents()
}
private Handle_PropertyChanged(...) { Update(); }
}
这是令人讨厌的事件注册,但目的是将这种丑陋从想要了解属性的类中移出。现在我进入了场景 2,它监控不同的对象/属性,并使用我的具体类作为抽象类的指南:
abstract class PropertySpy
{
protected PropertySpy(FooBase thingToMonitor)
{
_thingToMonitor = thingToMonitor;
RegisterForEvents()
}
protected abstract void RegisterForEvents()
// ...
}
哎呀。我在构造函数中有一个虚拟方法调用。理论上它对我的所有场景都是安全的,但是 R# 警告一直在挖我。我敢肯定,如果有一天我继续前进,它会导致一个需要一段时间才能解决的问题。该方法肯定需要使用派生类型的属性。
我可以放弃该方法并强制派生类型自己进行事件管理。那会破坏基类的目的。有人会忘记遵守合同,这会变成支持事件;我花了足够的时间编写文档。我想到的另一个方法是让 RegisterForEvents() publich 并要求用户在构建后调用它。 “创建然后初始化”模式在 .NET 中很糟糕,人们总是忘记。目前我正在玩弄另一个类的概念,该类执行通过构造函数注入的事件注册。然后派生类可以提供该类以实现与虚拟方法相同的效果而没有危险。但是进行注册的东西实际上需要与 PropertySpy 相同的属性接口;这似乎很乏味,但我想“丑陋且有效”比我所拥有的要好。
我缺少什么吗?如果论点有说服力,我什至会以“这是一个警告,而不是规则”作为答案。
【问题讨论】:
标签: c# constructor