如何传递委托引用给其他类,实现单个订阅者监听多个发布者?
嘿,这个场景我太熟悉了——重复给每个商店写监听逻辑确实又繁琐又容易出错!结合你的需求,我整理了几个更优雅的方案,你可以根据现有代码结构来选择:
更优雅地跨多个商店类监听对象添加事件
先再明确下你的核心需求:
有
VegetableStore和MeatStore两个类,分别处理继承自同一基类的VegType和MeatType对象;希望在独立类中监听这两个类的新对象添加事件,避免繁琐的重复实现。
方案1:抽象泛型基商店类,统一事件定义
如果还能修改商店类的结构,这是最推荐的方案——通过泛型基类把事件逻辑统一,让监听类只需要写一次通用处理逻辑,就能兼容所有子类商店。
示例代码:
// 所有产品的共同基类 public abstract class ProductType { } public class VegType : ProductType { } public class MeatType : ProductType { } // 泛型基商店类,统一定义添加事件 public abstract class StoreBase<T> where T : ProductType { // 事件用泛型参数,同时保证产品类型是ProductType的子类 public event EventHandler<ProductAddedEventArgs<T>> ProductAdded; // 封装事件触发逻辑,子类直接调用即可 protected void OnProductAdded(T product) { ProductAdded?.Invoke(this, new ProductAddedEventArgs<T>(product)); } } // 通用事件参数类 public class ProductAddedEventArgs<T> : EventArgs where T : ProductType { public T Product { get; } public ProductAddedEventArgs(T product) => Product = product; } // 具体蔬菜商店,继承基类 public class VegetableStore : StoreBase<VegType> { public void AddVeg(VegType veg) { // 这里写你的蔬菜添加业务逻辑 OnProductAdded(veg); } } // 具体肉类商店,同样继承基类 public class MeatStore : StoreBase<MeatType> { public void AddMeat(MeatType meat) { // 肉类添加业务逻辑 OnProductAdded(meat); } } // 独立监听类,只需要一套逻辑 public class ProductMonitor { // 通用订阅方法,适配所有StoreBase子类 public void SubscribeToStore<T>(StoreBase<T> store) where T : ProductType { store.ProductAdded += HandleProductAdded; } // 统一的事件处理方法,可通过is/as判断具体产品类型做差异化处理 private void HandleProductAdded(object sender, ProductAddedEventArgs<ProductType> e) { Console.WriteLine($"新增产品:{e.Product.GetType().Name}"); if (e.Product is VegType veg) { // 针对蔬菜的特殊处理逻辑 } else if (e.Product is MeatType meat) { // 针对肉类的特殊处理逻辑 } } }
这个方案的好处是从根源上统一了事件结构,后续新增其他类型的商店(比如SeafoodStore),只需要继承StoreBase<T>,监听类完全不需要修改,扩展性拉满。
方案2:利用事件协变性(适配已有代码结构)
如果已经有现成的VegetableStore和MeatStore,不想动它们的结构,那可以利用.NET 4.0+支持的委托协变性,把两个商店的事件绑定到同一个处理方法上。
示例代码:
// 原有类结构(假设无法修改) public abstract class ProductType { } public class VegType : ProductType { } public class MeatType : ProductType { } public class VegetableStore { public event EventHandler<VegAddedEventArgs> VegAdded; public void AddVeg(VegType veg) { VegAdded?.Invoke(this, new VegAddedEventArgs(veg)); } } public class VegAddedEventArgs : EventArgs { public VegType Veg { get; } public VegAddedEventArgs(VegType veg) => Veg = veg; } public class MeatStore { public event EventHandler<MeatAddedEventArgs> MeatAdded; public void AddMeat(MeatType meat) { MeatAdded?.Invoke(this, new MeatAddedEventArgs(meat)); } } public class MeatAddedEventArgs : EventArgs { public MeatType Meat { get; } public MeatAddedEventArgs(MeatType meat) => Meat = meat; } // 独立监听类 public class ProductMonitor { public void Subscribe(VegetableStore vegStore, MeatStore meatStore) { // 利用协变性,把不同事件绑定到同一个处理方法 vegStore.VegAdded += HandleProductAdded; meatStore.MeatAdded += HandleProductAdded; } // 统一处理方法,通过判断事件参数类型获取具体产品 private void HandleProductAdded(object sender, EventArgs e) { ProductType product = null; if (e is VegAddedEventArgs vegArgs) product = vegArgs.Veg; else if (e is MeatAddedEventArgs meatArgs) product = meatArgs.Meat; if (product != null) { Console.WriteLine($"新增产品:{product.GetType().Name}"); // 在这里添加具体的处理逻辑 } } }
这个方案不需要修改原有商店类,只需要在监听类中做一次参数类型判断,就能实现统一处理,非常适合已有代码的改造场景。
方案3:中介者模式(复杂系统的解耦利器)
如果你的系统后续会扩展更多商店类型或者监听者,那中介者模式是更好的选择——它能完全解耦商店和监听类,让两者都依赖中介者,避免直接引用。
示例代码:
// 中介者接口,定义通知行为 public interface IProductMediator { void NotifyProductAdded(ProductType product); void RegisterListener(IProductListener listener); } // 具体中介者,负责转发事件通知 public class ProductMediator : IProductMediator { private readonly List<IProductListener> _listeners = new(); public void RegisterListener(IProductListener listener) { _listeners.Add(listener); } public void NotifyProductAdded(ProductType product) { foreach (var listener in _listeners) { listener.OnProductAdded(product); } } } // 监听者接口,定义处理方法 public interface IProductListener { void OnProductAdded(ProductType product); } // 商店类依赖中介者,不再直接定义事件 public class VegetableStore { private readonly IProductMediator _mediator; public VegetableStore(IProductMediator mediator) => _mediator = mediator; public void AddVeg(VegType veg) { // 业务逻辑... _mediator.NotifyProductAdded(veg); } } public class MeatStore { private readonly IProductMediator _mediator; public MeatStore(IProductMediator mediator) => _mediator = mediator; public void AddMeat(MeatType meat) { // 业务逻辑... _mediator.NotifyProductAdded(meat); } } // 具体监听类,实现监听者接口 public class ProductMonitor : IProductListener { public void OnProductAdded(ProductType product) { Console.WriteLine($"新增产品:{product.GetType().Name}"); // 具体处理逻辑... } }
这个方案的优势是完全符合开闭原则,后续新增商店类型或者监听者,只需要实现对应的接口,不需要修改现有代码,非常适合复杂的大型系统。
内容的提问来源于stack exchange,提问作者Cerzi
相关产品推荐
相关产品推荐

