gpt4 book ai didi

c# - 需要一个 OOP 技巧

转载 作者:行者123 更新时间:2023-11-30 16:52:49 25 4
gpt4 key购买 nike

我想要一个引发事件的抽象类,这个事件将由具体类引发。

我想要的是,当我使用另一个类来监听这些事件时,委托(delegate)的签名应该具有具体类型而不是抽象类型,我不想转换它。

目前我想出了这个解决方案。它有效,但我不觉得它特别聪明,尤其是因为“愚蠢,没有意义……”部分。

这是我的解决方案:

public delegate void ClassAEventHandler<TClassA>(TClassA classA) where TClassA : ClassA;

//Abstract class that raise Event
public abstract class ClassA<TClassA> : where TClassA : ClassA
{
public event ClassAEventHandler<TClassA> onClassEventRaised;
private TClassA eventClassA;

public void registerEventClass(TClassA classA)
{
this.eventClassA = classA;
}

public void raiseClassEvent()
{
this.onClassEventRaised(this.eventClassA);
}
}

// Exemple of concrete type
public class ClassB : ClassA<ClassB> // <------ IT SEEMS DUMB
{
public void action()
{
//Do something then raise event
this.raiseClassEvent();
}

public void saySomething() {};
}

// Exemple of concrete type
public class ClassC : ClassA<ClassC> // <------ IT SEEMS DUMB
{
public void command()
{
//Do something then raise event
this.raiseClassEvent();
}

public void destroySomething() {};
}

//Class that listen to the event raised
public class MyEventListener
{
private ClassB classB;
private ClassC classC;

public MyEventListener()
{
this.classB = new ClassB();
this.classB.registerEventClass(this.classB); // <------ STUPID, DOESN'T MAKE SENSE......
this.classB.onClassEventRaised += classB_onClassEventRaised;

this.classC = new ClassC();
this.classC.registerEventClass(this.classC); // <------ STUPID, DOESN'T MAKE SENSE......
this.classC.onClassEventRaised += classC_onClassEventRaised;
}

public void classB_onClassEventRaised(ClassB classB)
{
classB.saySomething();
}

public void classC_onClassEventRaised(ClassC classC)
{
classC.destroySomething();
}

//What i don't want
/*
public void classB_onClassEventRaised(ClassA classA)
{
((classB)classA).saySomething();
}
*/
}

最佳答案

首先,您没有遵循 .NET 中的常规事件设计。

不要实现自己的委托(delegate),而是使用 EventHandler<TArgs> , 并创建 EventArgs 的派生类.

你的 CustomEventArgs应该有一个 T通用参数:

public class CustomEventArgs<T> where T : A
{
private readonly T _instance;

public CustomEventArgs(T instance)
{
_instance = instance;
}

public T Instance { get { return _instance; } }
}

此外,不要实现注册事件的自定义方式。如果您想封装如何将处理程序添加到事件中,您需要使用事件访问器

最后,您可以按如下方式实现您的类:

public class A<T> where T : A
{
private event EventHandler<CustomEventArgs<T>> _someEvent;

// An event accessor acts like the event but it can't be used
// to raise the event itself. It's just an accessor like an special
// event-oriented property (get/set)
public event EventHandler<CustomEventArgs<T>> SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}

protected virtual void RaiseSomeEvent(CustomEventArgs<T> args)
{
// If C# >= 6
_someEvent?.Invoke(this, args);

// Or in C# < 6
// if(_someEvent != null) _someEvent(this, args);
}
}


public class B : A<B>
{
public void DoStuff()
{
// It's just about raising the event accessing the whole
// protected method and give an instance of CustomEventArgs<B>
// passing current instance (i.e. this) to CustomEventArgs<T>
// constructor.
RaiseSomeEvent(new CustomEventArgs<B>(this));
}
}

现在,如果您尝试处理 SomeEvent ,你会得到 CustomEventArgs<B>输入为 B而不是 A :

B b = new B();
b.SomeEvent += (sender, args) =>
{
// args.Instance is B
B instance = args.Instance;
};
b.DoStuff(); // Raises SomeEvent internally

关于c# - 需要一个 OOP 技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32104184/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com