我正在考虑事件/委托系统的更复杂用途,并且有一个我无法找到解决方案的用例。
假设我有两个类都处理从同一个基类继承的对象:
public class VegetableStore {
List<VegType> vegtypes;
}
public class MeatStore {
List<MeatType> meatTypes;
}
// MeatType and VegType both extend abstract class FoodType
在一个单独的类中,我想在每次将一个新的VegType添加到VegetableStore中时监听,或者将新的MeatType添加到MeatStore。
现在,“简单”的方式似乎只是这样:
public class VegetableStore {
List<VegType> vegtypes;
public delegate void VegTypeAddedEventHandler(VegType vegType, bool added);
public event VegTypeAddedEventHandler VegTypeAdded;
//...
protected virtual void OnVegTypeAdded(VegType vegType, bool added) {}
}
public class MeatStore {
List<MeatType> meatTypes
public delegate void MeatTypeAddedEventHandler(MeatType meatType, bool added);
public event MeatTypeAddedEventHandler MeatTypeAdded;
//...
protected virtual void OnMeatTypeAdded(MeatType meatType, bool added) {}
}
然后在我的听众课上......
vegStore.VegTypeAdded += OnFoodTypeAdded;
meatStore.MeatTypeAdded += OnFoodTypeAdded;
void OnFoodTypeAdded(FoodType foodType, bool added) {}
尽管如此,这感觉要麻烦得多。
我想做的是拥有某种“父”代表,例如FoodTypeAddedEventHandler(object source, EventArgs e)
然后能够自动订阅订阅此事件的任何事件,订阅来自Meat和Veg的事件,这样我就可以包含一个中间事件管理器类
public event FoodTypeAddedEventHandler FoodTypeAdded
{
add
{
vegStore.VegTypeAdded += value;
meatStore.MeatTypeAdded += value;
{
remove
{
vegStore.VegTypeAdded -= value;
meatStore.MeatTypeAdded -= value;
}
}
麻烦的是。 vegStore和meatStore没有FoodTypeAddedHandler类型的委托,因此导致类型错误。
有没有切实可行的方法呢?似乎无法找到这个问题的合理直接的解决方案,但我觉得必须有一个。或者,我应该亲了吗?
答案 0 :(得分:2)
您可以使用这样的通用委托:
delegate void FoodTypeAddedEventHandler<in T>(T meatType, bool added) where T : FoodType;
然后代替VegTypeAddedEventHandler
,您拥有FoodTypeAddedEventHandler<VegType>
而不是MeatTypeAddedEventHandler
,而FoodTypeAddedEventHandler<MeatType>
代替FoodTypeAddedEventHandler
。最后代替FoodTypeAddedEventHandler<FoodType>
,您有public event FoodTypeAddedEventHandler<FoodType> FoodTypeAdded
{
add
{
vegStore.VegTypeAdded += value;
meatStore.MeatTypeAdded += value;
{
remove
{
vegStore.VegTypeAdded -= value;
meatStore.MeatTypeAdded -= value;
}
}
。经过这些修改,你的&#34;结合了#34;事件处理程序将编译正常:
Action<FoodType, bool>
或者 - 只需删除所有代理类型,然后使用Action<VegType, bool>
,Action<MeetType, bool>
和T
。那么你的代码也可以正常编译。
这是有效的,因为两个自定义委托都有第一个类型参数(in
)逆变(FoodTypeAddedEventHandler<FoodType>
修饰符)。这允许它接受派生类型的参数(因此,委托FoodType
可以接受签名,其中第一个参数不是VegType
,而是任何派生类型(例如Action
)。同样适用于Action
因为在in
中所有类型参数都是逆变的(使用 private val socketListeners: ArrayList<SocketContentListener> = ArrayList()
//add listener here
override fun subscribe(socketListener: SocketContentListener) {
socketListeners.add(socketListener)
}
private fun getSocketConnectListener()
: SocketContentListener {
/**
* Post received messages to listeners via Handler
* because handler helps to set all messages in order on main thread.
*/
return object : SocketContentListener {
override fun onUdpServerListenerCreated(inetAddress: InetAddress?, port: Int) {
val subscribers = ArrayList<SocketContentListener>(socketListeners)
for (listener in subscribers) {
Handler(Looper.getMainLooper()).post({ listener.onUdpServerListenerCreated(inetAddress, port) })
}
}
}
修饰符声明)。有关您可以在documentation中阅读的代理中的差异的更多信息。