【问题标题】:Inject delegate method from derived to base class using constructor使用构造函数将委托方法从派生类注入基类
【发布时间】:2013-11-10 01:20:21
【问题描述】:

今天我正在重构一个我创建的库,并在多个平台(WPF、WF、WP7、WP8)之间共享代码。

我的想法是我使用继承来扩展类中的功能。顶级类向客户端公开几个事件,该事件在一个方法中引发,该方法使用接受一些参数的构造函数向下传递给基类。

对象基本上是作为单例使用的。

例子:

public class SomeHandler : BaseHandler
{
   public event EventHandler<Custom1EventArgs> RequestCompleted = delegate {};
   public event EventHandler<Custom2EventArgs> ActionHandled = delegate { };

   protected SomeHandler()
      : base(new CustomUtil(), new CustomRepository(), 
       new AnotherRepository(ADelegateMethod), 
       AnotherDelegateMethod, AnotherOneDelegateMethod) {}

   #region [ Singleton ]
   public static SomeHandler Instance
      {   get { return Nested.instance;}  }

   class Nested
   {
       internal static readonly SomeHandler instance = new SomeHandler ();
   }
   #endregion

   private static void ADelegateMethod(Custom1EventArgs args)
   {
      Instance.RequestCompleted (Instance, args);
   }

   private static void AnotherDelegateMethod(
       Custom2EventArgs args, CustomObject result)
   {
       // Do stuff....
       AnotherCustomObject cusObj = new AnotherCustomObject(args);
       Instance.ActionHandled (Instance, cusObj);
   }

   private static void AnotherOneDelegateMethod(CustomObject result)
   {
       // Do some stuff...
   }
}

好的,如果你注意到了,我需要将委托方法标记为静态,因为注入发生在构造函数参数中。但这迫使我将事件设为静态。作为解决方法,我依赖于用户总是使用我的对象的 Instance 单例实例这一事实,尽管可以根据需要初始化对象,但 sealed 目前不是一个选项,因为它也用作基础在特定的特殊实现中继承类到另一个类。

将事件更改为静态是不是很糟糕?我觉得不太合适,你怎么看? 这样的设计还能改进吗?

实际上,我使用委托作为代码的一部分,需要在特定时间从其他对象new AnotherRepository(ADelegateMethod)BaseHandler 类执行,因此我基本上可以为客户提供信息。

【问题讨论】:

  • 不确定我是否理解正确,但整个“代表”厨房让我想起了虚拟方法调用,但只是以非常奇怪和真正精致的方式。 he he 不是吗? (如果不是,那有什么区别?)(还有为什么你需要一个单例?)
  • 与虚方法无关。虚拟方法将提供一个实现,子类也可以覆盖它或实现和调用基本实现。我发送一个委托(方法)以在运行时的特定点从父类或另一个类调用。我有理由希望用户只使用我的模块的一个实例。
  • 好吧,我只是说这些委托看起来像虚拟方法(按逻辑概念)。它们仍然是私有的,因此它们只能由父级调用,但虚拟方法应该是这样工作的(!)您不必在父级中定义方法主体 - 您可以将它们标记为抽象。 (你无论如何都应该覆盖它们)。但是如果你把它留空(基本的类方法体)——不需要在孩子身上做任何事情(包括把一些东西传递给父母)。如果我错过了什么,请告诉我。
  • 好的,现在你是对的,不使用虚拟方法而是抽象我可以删除委托,在子类中实现方法并在我需要的父类中调用它们,这确实可以让我免于 2 3 位代表,谢谢,从未想过此功能。这将修复 2 个委托,如果传递给另一个在基类中用作属性的类会发生什么情况?你怎么看?
  • 旁注:我已经对您的代码进行了格式化以删除太多空格...(我同意 Agat 的观点,即强制派生类传递委托而不是实现虚拟方法或使用正常事件很奇怪。 .. 此外,您已经发现设计很奇怪,因为您不能在构造函数中将实例方法作为委托传递...)

标签: c# oop dependency-injection delegates design-principles


【解决方案1】:

我建议更改的主要内容是:

  • 用相应的虚方法替换AnotherDelegateMethodAnotherOneDelegateMethod传递(然后从父类调用)。

至于其他事情,这一切都取决于你的类应该实现的逻辑。 可能,可能需要一些更多的解耦

  • 新的另一个存储库(ADelegateMethod)。这真的是一个棘手的问题如何正确地做每一件事——需要更多关于一般逻辑的信息,因为可能有不同的方法

    • 您也可以将其替换为 虚拟方法,例如 ADelegateMethod -- 与上述两个方法相同,但新的 AnotherRepository 为 protected virtual ISomeRepositoryInterface CreateRepositoryInstance()(例如);
    • 您可以在一些外部类中使用 依赖注入,这些类将使用您的处理程序来传递存储库,实际上与工具或其他存储库相同(但同样,一切都取决于关于一般逻辑);

    • 自定义处理程序的方法之一是将基本类设为 Generic 并通过提供一些具体类来继承子类,该逻辑与继承者,但大多只用在父类中。

关于活动:

  • 我建议您阅读 this 之类的内容,并大致熟悉 Rx(反应式扩展)——它们既现代又出色(您可以考虑使用它们代替事件 在很多情况下(如果不在这个处理程序类中,那么在其他一些情况下)。 (但是,目前我看不到你真的需要在课堂上使用事件的情况。

另外,至于@durilka 的回答(但是,考虑到他在俄语中的绰号“骗子”,他相信他真的很有趣,呵呵):他正确地提到了(在我开始之前):

  • 删除嵌套类并替换为静态构造函数(如果在基类中)。但这必须仔细重新考虑(特别是如果您真的广泛使用多线程)。

【讨论】:

  • 感谢您的宝贵时间。考虑这是整个概念的一个示例,但如果需要,我会寻找更多的解耦,假设 SomeHandler 是负责注入依赖项的客户端,使用它的客户端不应该做任何事情。具体的类构造函数实际上是父类的接口。我将重新考虑建议。是的,多线程很重要,它将被使用。
【解决方案2】:

摆脱嵌套。将默认构造函数声明为私有。在返回现有实例或创建新实例(又名return instance ?? instance = new SomeHandler())时在您的 Instance 属性中使用它。并开始考虑从委托转移到某种消息总线。

【讨论】:

  • 这是线程安全的吗?消息总线是什么意思?按照建议实现抽象方法?
  • 为了线程安全,添加双重锁定或使用 Lazy。我所说的消息总线是指接受特定消息的订阅者并允许在不知道是否有人在听的情况下发送这些消息的类。
  • 我想要一个有关消息总线的示例或演示此模式的链接。谢谢。
  • en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern 我猜,搜索“消息总线”目前在 google 上被夸大了,包含不必要的企业内容。
  • 我只是想从你的研究和经验中得到一些关于这个主题的东西,并不是我不知道如何/在哪里打字。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-19
  • 2011-05-03
  • 2018-07-21
  • 2015-08-18
相关资源
最近更新 更多