我正在使用Model View Presenter模式处理WinForms应用程序。每次我声明要在View中引发的事件处理程序时,我最终也会在我的Presenter类中声明它,因为它必须处理该事件。
// Code in the View Class:
//Note: Here is the declaration I am duplicating in every class that
//handles the raising of the event (i.e. ProductSaveButtonEventRaised)
public event EventHandler ProductSaveButtonEventRaised;
private void SaveBtn_Click(object sender, EventArgs e)
{
if (ProductSaveButtonEventRaised!= null) //Check if any subscribed )
{
ProductSaveButtonEventRaised(this, eventArgs); // Notify all subscribers
}
}
// Code in the Presenter Class:
// Note: Here the EventHandler declaration (ProductSaveButtonEventRaised)
// is repeated same as in the View. Is there another way to do this
// Other than duplicating the declaration in every class that needs to
// handle the event?:
public event EventHandler ProductSaveButtonEventRaised;
private void SubscribeEvents()
{
_view.ProductSaveButtonEventRaised += new EventHandler(OnProductSaveButtonEventRaised);
}
private void OnProductSaveButtonEventRaised(object sender, EventArgs e)
{
//Event is raised again from the Presenter so it is forwarded to another
//Presenter which is the class that created this Presenter
if (ProductSaveButtonEventRaised!= null) //Check if any subscribed )
{
ProductSaveButtonEventRaised(this, eventArgs); // Notify all subscribers
}
}
除了为两个类创建某种类的父类以共享和继承事件声明之外,我还能做什么呢?我不会多次声明事件处理程序来覆盖需要处理事件的类由观点提出?
答案 0 :(得分:0)
我有一个解决方案。但我肯定会建议你继续做你正在做的事情而不是替代(我已经创造了) - 因为它是更清晰的代码。
这个答案只是为了说明如何做到这一点。 我已经编写了这个例子,因此它可能看起来不太真实
答案:
你可以拥有一个保存和引发事件的Base类,View和Presenter类都可以继承这个类(如果你的任何一个视图或presenter类已经继承了其他类,你就无法实现下面的逻辑)
public class BaseEventClass
{
public string Name;
public event EventHandler ProductSaveButtonEventRaised;
public void RaiseAnEvent(BaseEventClass thisObj)
{
if (ProductSaveButtonEventRaised != null)
{
ProductSaveButtonEventRaised(thisObj, EventArgs.Empty);
}
}
}
public class ViewClass : BaseEventClass
{
public void LogicWhichRaiseAnEvent(string name)
{
Name = name;
base.RaiseAnEvent(this);
}
}
public class PresenterClass : BaseEventClass
{
public void LogicWhichRaiseAnEvent(string name)
{
Name = name;
base.RaiseAnEvent(this);
}
}
以及引发事件和听力事件的调用逻辑将如下所示。
public static void Main()
{
ViewClass v = new ViewClass();
v.ProductSaveButtonEventRaised += ViewEventHandler;
v.LogicWhichRaiseAnEvent("view");
PresenterClass p = new PresenterClass();
p.ProductSaveButtonEventRaised += PresenterEventHandler;
p.LogicWhichRaiseAnEvent("presenter");
}
static void ViewEventHandler(object sender, EventArgs e)
{
Console.WriteLine(((ViewClass)sender).Name);
}
static void PresenterEventHandler(object sender, EventArgs e)
{
Console.WriteLine(((PresenterClass)sender).Name);
}
旁注:这里我在Base类中创建了Name
属性,因此通过查看Name
属性,您可以确定该事件已正确引发。
答案 1 :(得分:0)
您面临的问题是事件与常规对象不同。您不能将它们传递给其他类来订阅它们,也不能将它们公开为属性。但是,您可以使用Reactive Extensions将它们变为可观察的,以便可以。对于这样的用例,它是designed。
要显示这些功能,请参见以下示例:
public class View
{
public event EventHandler ProductSaveButtonEventRaised;
}
public class Presenter
{
// Obervables are first class citizens, meaning you can pass them around or expose them as a property
public IObservable<EventPattern<EventArgs>> ProductSavedEvents { get; private set;}
public Presenter(View view)
{
// Turn a regular event into an Observable
ProductSavedEvents = Observable.FromEventPattern<EventHandler, EventArgs>(
h => view.ProductSaveButtonEventRaised += h,
h => view.ProductSaveButtonEventRaised -= h);
}
}
public class PresenterCreator
{
Presenter presenter = new Presenter(new View());
public void Subscribe()
{
// Act on a save button event
presenter.ProductSavedEvents.Subscribe(@event => Console.WriteLine(@event));
var otherConsumer = new OtherConsumer(presenter.ProductSavedEvents);
}
}
public class OtherConsumer
{
// You can pass observables just like any other object. Can't do that with events
public OtherConsumer(IObservable<EventPattern<EventArgs>> ProductSavedEvents)
{
// Act on a save button event
ProductSavedEvents.Subscribe(@event => Console.WriteLine(@event));
}
}