可以使用哪种替代方法来避免暴露事件和接口。
我有一个具有确定生命周期的类:创建,修改,......
客户主要GUIs
需要连接到该类的生命周期,所以最简单的方法是暴露事件,同时我需要移动一些责任 - 这在生命周期中发生 - 这个班让我想出了这个解决方案:
Interface ILifeCycle
{
void OnCreated(...);
void OnModified(...);
// ...
}
classA
{
private ILifeCycle lifeCycle;
/// ...
public event EventHandler Created(object sender, EventArgs args);
public event EventHandler Modified(object sender, EventArgs args);
/// ...
protected void OnCreated()
{
lifeCycle.OnCreated(...);
if(Created!=null)
Created(this,EventArgs.Empty);
}
protected void OnModified()
{
lifeCycle.OnModified(...);
if(Modified!=null)
Modified(this,EventArgs.Empty);
}
/// ...
}
这样做我可以注入一个实现Logger
的{{1}},因此将日志记录职责移到自己的类中,
但感觉好像会有很多重复。
你会建议用什么干净的替代品来实现这个目标?
答案 0 :(得分:1)
一般来说,Interface
和Events/Delegates
用于两种截然不同的方法。让我们先描述一下 -
接口:接口的主要目的是为该接口的所有实现强制执行某些功能。无论何时在子类中实现它,都会覆盖超类的实现。例如 -
interface IA
{
void test();
}
class A : IA
{
public void test(){
}
}
class B : A
{
public void test(){
//you can only go up by calling base.test(), but cannot move down, because you do not know whether there is an implementation down the tree or not. So you cannot call it.
}
}
class C : B
{
public void test(){
//you can only go up by calling base.test(), but cannot move down, because you do not know whether there is an implementation down the tree or not. So you cannot call it.
}
}
正如您所看到的,通过界面,您只能回头看但不能向前看,并假设将会有更多的实现。
事件:为不同目的创建事件。我们只想说你想给开发人员一些依赖某些活动的工具,并根据这些活动和变化做一些其他活动,最重要的是他们将来会实现这一点。事件将不依赖于您的实现,他们将只订阅它并基于此做一些事情。无论它们是否存在,您自己的实现都不会更改,或者您自己的代码的行为不会根据它们而更改。换句话说,您只能向下移动树。基类捕获了事件,然后将它们传播到树中。
这些是Interface
和Events
的常用用法,它们是以这种方式使用的。但是编码并不是完全不可能完全取决于接口,反之亦然,即代码完全依赖于事件,但这不是它们的意图。
在这种情况下:在您的情况下,我认为您正在尝试实现一个不依赖于彼此但又会订阅事件的模块化系统。还有其他架构和模式,特别是IOC容器对您非常有用,完全取决于接口,您不需要事件。一些.net IOC容器是AutoFac,Castle.Windsor,MEF
我自己,就像MEF一样,这是我几年前写的关于MEF的帖子,向您展示如何在容器内注入运行时处理程序 -
http://mahmudulislam.me/2012/04/20/1a-managed-extensibility-framework-introduction/
顺便说一句,文章有点陈旧,我正在努力更新这篇文章。IOC解决方案:我正在为MEF提供一个可能的解决方案 -
Interface ILifeCycle
{
void OnCreated(...);
void OnModified(...);
...
}
[Export(typeof(ILifeCycle))] //export our classes for injection
classB : ILifeCycle{
public void OnCreated(...)
{
....
}
public void OnModified(...){
}
}
[Export(typeof(ILifeCycle))] //export our classes for injection
classC : ILifeCycle{
public void OnCreated(...)
{
....
}
public void OnModified(...){
}
}
classA
{
[ImportMany] //get all exported classes for injection
private IList<ILifeCycle> _observers;
protecetd void OnCreated()
{
//use MEF to build composition and then do the following
foreach(var o in _observers){
o.OnCreated(...);
}
}
protecetd void OnModified()
{
//use MEF to build composition and then do the following
foreach(var o in _observers){
o.OnModified(...);
}
}
...
}
这是一个非常基本的解决方案。但在您的情况下,您可能希望使用异步编程。因为事件和接口之间存在很大差异。默认情况下,事件处理程序在单独的线程中调用,因此它不会暂停调用者,但是接口实现将挂起调用者,直到方法完成。因此,请确保使用异步编程来阻止主进程。
Asynchronous Programming with Async and Await (C# and Visual Basic)
答案 1 :(得分:0)
我不确定我是否理解你,但我认为你担心实施ILifeCycle
的不同类型的重复。所以,你可以利用继承:
abstract class LifeCycleBase
{
public void OnCreated(...)
{
.....
}
public void OnModified(...);
{
.....
}
...
}
class LifeCycleLoger : LifeCycleBase
{
public void OnCreated(...)
{
....
base.OnCreate();
}
....
}