简体   繁体   English

使用构造函数将委托方法从派生注入基类

[英]Inject delegate method from derived to base class using constructor

Today I was re-factoring a library that I created and share code across multiple platforms (WPF, WF, WP7, WP8). 今天,我正在重构一个库,该库可以在多个平台(WPF,WF,WP7,WP8)上创建和共享代码。

The idea is that I use inheritance to extend functionality in classes. 这个想法是我使用继承来扩展类中的功能。 The top class expose couple of events to the client, this event is raised in a method that is passed down to the base class using the constructors that accept some parameters. 顶级类向客户端公开了几个事件,此事件在方法中引发,该方法使用接受某些参数的构造函数传递给基类。

The object is basically used as a singleton. 该对象基本上用作单例。

Example: 例:

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...
   }
}

OK, if you have noticed, I need to mark the delegate methods as static because the inject is happened in the constructor parameters. 好的,如果您已经注意到,我需要将委托方法标记为静态,因为在构造函数参数中发生了注入。 But this forced me to make the events static. 但这迫使我将事件静态化。 To workaround I relied to the fact that the user is always using the Instance singleton instance of my object, though the object can be initialized if they want, sealed is not an option at the moment because it is also used as base inherited class to another class in a specific special implementation. 要解决此问题,我依赖于这样的事实,即用户始终使用我的对象的Instance singleton实例,尽管可以根据需要初始化该对象,但目前还不能选择sealed ,因为它还用作另一个对象的基继承类。类在特定的特殊实现中。

Is it bad to change the events to static? 将事件更改为静态是否不好? It doesn't seem proper to me, what do you think? 对我来说似乎不合适,您怎么看? Can this design get better? 这种设计可以改善吗?

Actually I use the delegates as a part of code that needs to be executed in a specific time from other objects new AnotherRepository(ADelegateMethod) or the BaseHandler class so i can basically provide the client with information. 实际上,我将委托用作需要在特定时间内从其他对象new AnotherRepository(ADelegateMethod)BaseHandler类执行的代码的一部分,因此我基本上可以为客户端提供信息。

The main thing I would suggest to change is: 我建议更改的主要内容是:

  • to replace AnotherDelegateMethod and AnotherOneDelegateMethod passing (and then calling from parent class) with corresponding virtual methods . 用相应的虚方法替换传递的AnotherDelegateMethodAnotherOneDelegateMethod (然后从父类调用)。

As for another things, that all depends on the logic your class is suppose to implement. 至于另一件事,这完全取决于您的类要实现的逻辑。 Possibly , some more decoupling might be needed. 可能需要更多的去耦

  • new AnotherRepository(ADelegateMethod). 新的AnotherRepository(ADelegateMethod)。 That's really a tough question how to do everything right -- more info about general logic would be needed, as different approaches possible : 确实是一个棘手的问题,如何正确地做所有事情-由于可能采用不同的方法 ,因此需要更多有关常规逻辑的信息:

    • you can replace that also with virtual methods , like ADelegateMethod -- the same way as mentioned two above, but new AnotherRepository as protected virtual ISomeRepositoryInterface CreateRepositoryInstance() (for instance); 您也可以用虚拟方法来代替它,例如ADelegateMethod-与上面提到的两种方法相同,但是新的AnotherRepository作为protected virtual ISomeRepositoryInterface CreateRepositoryInstance() (例如);
    • you can use dependency injection into some outside classes which would use your handler to pass the the repository, the same, actually, as Tools or another repository (but, again, everything depends on the general logic); 您可以使用依赖注入到一些外部类中,这些类将使用您的处理程序来传递存储库,实际上与工具或另一个存储库相同(但同样,一切都取决于通用逻辑);

    • one of the ways to customize your handler(s) is to make the basic class as Generic and to inherit the children with providing some concrete class, which logic is related exactly to the inheritor, but mostly used only in parent class. 定制处理程序的一种方法是将基本类设置为Generic,并通过提供一些具体的类来继承子级,该逻辑与继承者完全相关,但大多数仅在父类中使用。

About events: 关于事件:

  • I would recommend you to read something like this and generally get familiar with Rx (Reactive Extensions) -- they are modern and awesome (you can consider using them instead of events in many cases ( if not in this handler class, then in some other situations )). 我建议您阅读这样的内容,并且通常熟悉Rx(响应式扩展) -它们非常现代且很棒(在许多情况下您可以考虑使用它们而不是事件如果不在此处理程序类中,则在其他情况下)情况 ))。 (However, currently I can't see the situation when you really would need to use events in your class). (但是,目前我看不到当您确实需要在类中使用事件时的情况)。

Also, as for @durilka's answer (however, that's really funny to trust him considering his nickname "liar" from Russian, he he): he mentioned correctly (before I got into that) about: 此外,至于@durilka的回答(但是,考虑到他的俄语昵称“骗子”,相信他真的很有趣):他正确地提到了(在我进入之前):

  • to remove the nested class and replace with static constructor (if in base class). 删除嵌套类并替换为静态构造函数 (如果在基类中)。 But that must be carefully rethinked (especially, if you really use multithreading widely). 但这必须仔细地重新考虑(特别是如果您真的广泛使用多线程)。

Get rid of the Nested. 摆脱嵌套。 Declare default constructor private. 声明私有的默认构造函数。 Use it in your Instance property while returning existing instance or creating a new one (aka return instance ?? instance = new SomeHandler() ). 在返回现有实例或创建新return instance ?? instance = new SomeHandler() (又名return instance ?? instance = new SomeHandler() ),在您的Instance属性中使用它。 And start thinking of moving from delegates to some kind of message bus. 并开始考虑从代表转移到某种消息总线。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM