Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将委托引用传递给另一个类,以便一个订阅者可以侦听多个发布者?_C#_Events_Delegates - Fatal编程技术网

C# 将委托引用传递给另一个类,以便一个订阅者可以侦听多个发布者?

C# 将委托引用传递给另一个类,以便一个订阅者可以侦听多个发布者?,c#,events,delegates,C#,Events,Delegates,我正在研究事件/委托系统更复杂的用途,有一个我找不到解决方案的用例 假设我有两个类,它们都处理从同一基类继承的对象: public class VegetableStore { List<VegType> vegtypes; } public class MeatStore { List<MeatType> meatTypes; } // MeatType and VegType both extend abstract class FoodType 这

我正在研究事件/委托系统更复杂的用途,有一个我找不到解决方案的用例

假设我有两个类,它们都处理从同一基类继承的对象:

public class VegetableStore {
    List<VegType> vegtypes;
}
public class MeatStore {
    List<MeatType> meatTypes;
}
// MeatType and VegType both extend abstract class FoodType
这感觉比可能的要混乱得多

我想做的是使用某种“父”委托,例如
FoodTypeAddedEventHandler(objectsource,EventArgs e)
然后能够自动订阅订阅此事件的任何事件,订阅来自Meat和Veg的事件,这样中间eventmanager类就可以包含

public event FoodTypeAddedEventHandler FoodTypeAdded
{
    add
    {
        vegStore.VegTypeAdded += value;
        meatStore.MeatTypeAdded += value;
    {
    remove
    {
        vegStore.VegTypeAdded -= value;
        meatStore.MeatTypeAdded -= value;
    }
}
问题是。vegStore和meatStore没有FoodTypeAddHandler类型的委托,因此这会导致类型错误


有没有切实可行的办法?似乎找不到一个合理的直截了当的方法来解决这个问题,但我觉得肯定有一个。或者,我应该亲吻它吗?

您可以像这样使用通用委托:

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) {}
}
delegate void FoodTypeAddedEventHandler<in T>(T meatType, bool added) where T : FoodType;
或者-只需删除所有代理类型并使用
操作
操作
操作
。然后,您的代码也可以很好地编译


这是因为两个自定义委托都有其第一个类型参数(
T
)逆变(修改器中的
)。这允许它接受派生类型的参数(因此,委托
FoodTypeAddedEventHandler
可以接受签名,其中第一个参数不完全是
FoodType
,而是任何派生类型(例如
VegType
)。这同样适用于
操作
,因为在
操作
中,所有类型参数也是逆变的(在
修饰符中用
声明)。有关代理差异的更多信息,您可以阅读。

首先,我要删除您的特定代理类型-它们不会比仅使用具有完全相同签名的
EventHandler
给您带来任何好处。当您改为使用
EventHandler
时,问题应该会消失(无论如何,我怀疑——这只是通过检查)。我的示例不清楚,因为我确实使用了自定义参数-将进行整理。你是对的,EventHandler将以其他方式解决无法正常工作的问题,因为
vegStore.VegTypeAdded
将与
FoodTypeAddedEventHandler
@jonsket为什么?我尝试过了,它编译得很好(虽然没有试着跑).Note我说过要更改所有委托类型,包括vegStore.VegTypeAdded。@JonSkeet可能您没有注意到VegType和MeatType都继承自同一个类FooType?这在操作代码中没有显示,但在该代码的注释中提到了。但这不允许您订阅事件-您需要在另一个方向上使用通用变量。Pu是这样的吗:如果事件是用
MeatType
值引发的,您希望
vegStore.VegTypeAdded
处理程序如何接受该值?@JonSkeet我不希望这样,但我不明白这是怎么可能的。
FoodTypeAdded
事件不可开票,您只能订阅\取消订阅它(OP不需要调用它,只需订阅即可)。仅
VegTypeAdded
(类型
FoodTypeAddedEventHandler
)和
MeatTypeAdded
(类型
FoodTypeAddedEventHandler
)可以调用。我不知道如何使用委托订阅VegTypeAdded,其中第一个参数是给定代码的
MeatType
。您可以使用
VegType
FoodType
(通过
FoodTypeAdded
伪事件)进行订阅。
delegate void FoodTypeAddedEventHandler<in T>(T meatType, bool added) where T : FoodType;
public event FoodTypeAddedEventHandler<FoodType> FoodTypeAdded
{
    add
    {
        vegStore.VegTypeAdded += value;
        meatStore.MeatTypeAdded += value;
    {
    remove
    {
        vegStore.VegTypeAdded -= value;
        meatStore.MeatTypeAdded -= value;
    }
}